     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.2
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.15 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 04/02/2016 (v0.2.1.0) ]
    13                                  ;	 31/12/2021 - BugFix and Code Optimization (v0.2.1.1)
    14                                  ;	 26/02/2022 - Code Optimization and BugFix (v0.2.1.2) - 02/01/2022
    15                                  ;
    16                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    17                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    18                                  ; <Bell Laboratories (17/3/1972)>
    19                                  ; <Preliminary Release of UNIX Implementation Document>
    20                                  ;
    21                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    22                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    23                                  ;
    24                                  ; ****************************************************************************
    25                                  ; 31/12/2021 - 26/02/2022
    26                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    27                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    28                                  
    29                                  ; 02/01/2022 - Code Optimization
    30                                  ; Runix Kernel v0.2.1.2
    31                                  ; 24/12/2021 - BugFix and Code Optimization
    32                                  ; Runix Kernel v0.2.1.1 
    33                                  
    34                                  ; 24/12/2013
    35                                  
    36                                  ; Entering protected mode:
    37                                  ; Derived from 'simple_asm.txt' source code file and 
    38                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    39                                  ; (gregor.brunmar@home.se)
    40                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    41                                  ;
    42                                  
    43                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    44                                  ; by Michael Chourdakis (2009) 
    45                                  ; http://www.codeproject.com/Articles/45788/
    46                                  ; http://www.michaelchourdakis.com
    47                                  ;
    48                                  
    49                                  ; Global Descriptor Table:
    50                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    51                                  ; by Linus Torvalds (1991-1992)
    52                                  ;
    53                                  
    54                                  KLOAD	equ 10000h ; Kernel loading address
    55                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    56                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    57                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    58                                  ; 19/03/2015
    59                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    60                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    61                                  ; 24/03/2015
    62                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    63                                  ; 19/03/2015
    64                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    65                                  		     ; (at the end of the 1st 4MB)
    66                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    67                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    68                                  
    69                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
    70                                  ;; 27/12/2013
    71                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    72                                  
    73                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    74                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    75                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    76                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    77                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    78                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    79                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    80                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    81                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    82                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    83                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    84                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    85                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    86                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    87                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    88                                  ;----------------------------------------
    89                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    90                                  ;-----------------------------------------------------------------------------
    91                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    92                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    93                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    94                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    95                                  
    96                                  ; Memory Allocation Table Address
    97                                  ; 05/11/2014
    98                                  ; 31/10/2014
    99                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
   100                                  					; the 1st 1 MB memory space.
   101                                  					; (This address must be aligned
   102                                  					;  on 128 KB boundary, if it will be
   103                                  					;  changed later.)
   104                                  					; ((lower 17 bits of 32 bit M.A.T.
   105                                  					;   address must be ZERO)).
   106                                  					; ((((Reason: 32 bit allocation 
   107                                  					;     instructions, dword steps)))
   108                                  					; (((byte >> 12 --> page >> 5)))  
   109                                  ;04/11/2014	
   110                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   111                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   112                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   113                                  ;
   114                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   115                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   116                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   117                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   118                                  
   119                                  ; 17/02/2015 (unix386.s)
   120                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   121                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   122                                  ;
   123                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   124                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   125                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   126                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   127                                  
   128                                  
   129                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   130                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   131                                  ;
   132                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   133                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   134                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   135                                  		      ; otherwise it is standard FDPT with physical values 	
   136                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   137                                  		      ; (obsolete for IDE/ATA drives)
   138                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   139                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   140                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   141                                  			; Bit 4 : Reserved. Always 0
   142                                  			; Bit 3 : Set to 1 if more than 8 heads
   143                                  			; Bit 2-0 : Reserved. Alsways 0
   144                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   145                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   146                                  
   147                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   148                                  ; (11 bytes long) will be used by diskette handler/bios
   149                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   150                                  
   151                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   152                                  
   153                                  [ORG 0]
   154                                  
   155                                  KSTART: ; 01/01/2022
   156                                   
   157                                  	; 12/11/2014
   158                                  	; Save boot drive number (that is default root drive)
   159 00000000 8816[EA65]              	mov	[boot_drv], dl ; physical drv number
   160                                  
   161                                  	; Determine installed memory
   162                                  	; 31/10/2014
   163                                  	;
   164 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   165 00000007 CD15                    	int	15h	   ; for large configurations
   166 00000009 7308                    	jnc	short chk_ms
   167 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   168 0000000D CD15                    	int	15h
   169                                  	;	   
   170                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   171                                  	;out	70h, al ; select CMOS register
   172                                  	;in	al, 71h ; read data (1 byte)
   173                                  	;mov	cl, al
   174                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   175                                  	;out	70h, al ; select CMOS register
   176                                  	;in	al, 71h ; read data (1 byte)
   177                                  	;mov	ch, al
   178                                   	;      
   179 0000000F 89C1                    	mov	cx, ax
   180 00000011 31D2                    	xor	dx, dx
   181                                  chk_ms:
   182 00000013 890E[8468]              	mov	[mem_1m_1k], cx
   183 00000017 8916[8868]              	mov	[mem_16m_64k], dx
   184                                  	; 05/11/2014
   185                                  	;and	dx, dx
   186                                  	;jz	short L2
   187 0000001B 81F90004                        cmp     cx, 1024
   188 0000001F 7351                    	jnb	short L0
   189                                  		 ; insufficient memory_error	
   190                                  		 ; Minimum 2 MB memory is needed... 
   191                                  	; 05/11/2014
   192                                  	; (real mode error printing)
   193 00000021 FB                      	sti
   194 00000022 BE[3600]                	mov	si, msg_out_of_memory
   195 00000025 BB0700                  	mov	bx, 7
   196 00000028 B40E                    	mov	ah, 0Eh	; write tty
   197                                  oom_1:
   198 0000002A AC                      	lodsb
   199 0000002B 08C0                    	or	al, al
   200 0000002D 7404                    	jz	short oom_2
   201 0000002F CD10                    	int	10h
   202 00000031 EBF7                    	jmp	short oom_1
   203                                  oom_2:
   204 00000033 F4                              hlt
   205 00000034 EBFD                    	jmp	short oom_2
   206                                  
   207                                  ; 02/01/2022
   208                                  ; 05/11/2014
   209                                  msg_out_of_memory:
   210 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   211 00000039 496E73756666696369-             db      'Insufficient memory !'
   211 00000042 656E74206D656D6F72-
   211 0000004B 792021             
   212 0000004E 0D0A                    	db	0Dh, 0Ah
   213                                  _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc')
   214 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   214 00000059 324D42206D656D6F72-
   214 00000062 79206973206E656564-
   214 0000006B 65642E29           
   215 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   216                                  
   217                                  L0:
   218                                  %include 'diskinit.inc' ; 07/03/2015
   219                              <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC
   220                              <1> ; Last Modification: 02/01/2022
   221                              <1> 
   222                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   223                              <1> 
   224                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   225                              <1> 
   226                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   227                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   228                              <1> ;L0:
   229                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   230                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   231 00000072 BA7F00              <1> 	mov	dx, 7Fh
   232                              <1> L1:	
   233 00000075 FEC2                <1> 	inc	dl
   234 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   235                              <1> 			; Phoenix EDD v1.1 - EDD v3
   236 00000079 BBAA55              <1> 	mov	bx, 55AAh
   237 0000007C CD13                <1> 	int 	13h
   238 0000007E 721A                <1> 	jc	short L2
   239                              <1> 
   240 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   241 00000084 7514                <1> 	jne	short L2
   242 00000086 FE06[ED65]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   243 0000008A 8816[EC65]          <1>         mov     [last_drv], dl  ; last hard disk number
   244 0000008E BB[7065]            <1> 	mov	bx, hd0_type - 80h
   245 00000091 01D3                <1> 	add	bx, dx	 
   246 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   247                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   248                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   249                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   250                              <1>                          ;            (EDD) ready (DPTE ready)
   251                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   252                              <1>                          ;            (EDD-3)
   253                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   254 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   255 00000098 72DB                <1> 	jb	short L1
   256                              <1> L2:
   257                              <1> 	; 23/11/2014
   258                              <1> 	; 19/11/2014
   259 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   260                              <1> 	; 04/02/2016 (esi -> si)
   261 0000009C BE[EE65]            <1> 	mov	si, fd0_type
   262                              <1> L3:
   263                              <1> 	; 14/01/2015
   264 0000009F 8816[EB65]          <1> 	mov	[drv], dl
   265                              <1> 	;
   266 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   267 000000A5 CD13                <1> 	int	13h	
   268 000000A7 7210                <1> 	jc	short L4
   269                              <1> 		; BL = drive type (for floppy drives)
   270                              <1> 		; DL = number of floppy drives
   271                              <1> 		;		
   272                              <1> 		; ES:DI = Address of DPT from BIOS
   273                              <1> 		;
   274 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   275                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   276                              <1> 	; 14/01/2015
   277 000000AB E8BB01              <1> 	call	set_disk_parms
   278                              <1> 	; 10/12/2014
   279 000000AE 81FE[EE65]          <1> 	cmp	si, fd0_type
   280 000000B2 7705                <1> 	ja	short L4
   281 000000B4 46                  <1> 	inc	si ; fd1_type
   282 000000B5 B201                <1> 	mov	dl, 1
   283 000000B7 EBE6                <1> 	jmp	short L3
   284                              <1> L4:
   285                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   286 000000B9 B27F                <1> 	mov	dl, 7Fh
   287                              <1> 	; 24/12/2014 (Temporary)
   288 000000BB 803E[ED65]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   289                              <1> 	;ja	L10       ; yes, all fixed disk operations
   290                              <1> 			  ; will be performed according to
   291                              <1> 			  ; present EDD specification
   292                              <1> 	; 02/01/2022
   293 000000C0 7603                <1> 	jna	short L5
   294 000000C2 E99100              <1> 	jmp	L10
   295                              <1> L5:
   296 000000C5 FEC2                <1> 	inc 	dl
   297 000000C7 8816[EB65]          <1>         mov     [drv], dl
   298 000000CB 8816[EC65]          <1>         mov     [last_drv], dl ; 14/01/2015
   299 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   300 000000D1 CD13                <1> 	int	13h	; (conventional function)
   301                              <1> 	;jc	L13	; fixed disk drive not ready
   302                              <1> 	; 02/01/2022
   303 000000D3 7303                <1> 	jnc	short L6
   304 000000D5 E98301              <1> 	jmp	L13
   305                              <1> L6:
   306 000000D8 8816[ED65]          <1>         mov     [hdc], dl ; number of drives
   307                              <1> 	;; 14/01/2013
   308                              <1> 	;;push	cx
   309 000000DC E88A01              <1> 	call	set_disk_parms
   310                              <1> 	;;pop	cx
   311                              <1> 	;
   312                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   313 000000DF 8A16[EB65]          <1>         mov     dl, [drv]
   314 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   315 000000E6 80FA80              <1> 	cmp	dl, 80h
   316 000000E9 7603                <1> 	jna	short L7
   317 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   318                              <1> L7:	
   319 000000EE 31C0                <1> 	xor	ax, ax
   320 000000F0 8ED8                <1> 	mov	ds, ax
   321 000000F2 8B37                <1>         mov     si, [bx]
   322 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   323 000000F7 8ED8                <1> 	mov	ds, ax
   324 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   325                              <1> 	;jne	L12 ; invalid FDPT
   326                              <1> 	; 02/01/2022
   327 000000FC 7403                <1> 	je	short L7_8
   328 000000FE E95601              <1> 	jmp	L12
   329                              <1> L7_8:
   330 00000101 BF0000              <1> 	mov	di, HD0_DPT
   331 00000104 80FA80              <1> 	cmp	dl, 80h
   332 00000107 7603                <1> 	jna	short L8
   333 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   334                              <1> L8:
   335                              <1> 	; 30/12/2014
   336 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   337 0000010F 8EC0                <1> 	mov	es, ax
   338                              <1> 	; 24/12/2014
   339 00000111 B90800              <1> 	mov	cx, 8
   340 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   341 00000116 8CC8                <1> 	mov	ax, cs
   342 00000118 8ED8                <1> 	mov	ds, ax
   343                              <1> 	; 02/02/2015
   344 0000011A 8A0E[EB65]          <1>         mov     cl, [drv]
   345 0000011E 88CB                <1> 	mov	bl, cl
   346 00000120 B8F001              <1> 	mov	ax, 1F0h
   347 00000123 80E301              <1> 	and	bl, 1
   348 00000126 7406                <1> 	jz	short L9
   349 00000128 C0E304              <1> 	shl	bl, 4
   350 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   351                              <1> L9:
   352 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   353 0000012F 050602              <1> 	add	ax, 206h
   354 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   355 00000133 88D8                <1> 	mov	al, bl
   356 00000135 04A0                <1> 	add	al, 0A0h
   357 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   358                              <1> 	;
   359 00000138 FE06[EB65]          <1> 	inc	byte [drv]
   360 0000013C BB[7065]            <1> 	mov	bx, hd0_type - 80h
   361 0000013F 01CB                <1> 	add	bx, cx
   362 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   363 00000144 A0[ED65]            <1> 	mov	al, [hdc]
   364 00000147 FEC8                <1> 	dec	al
   365                              <1> 	;jz	L13
   366                              <1> 	; 02/01/2022
   367 00000149 7408                <1> 	jz	short L9_10
   368 0000014B 80FA80              <1> 	cmp	dl, 80h
   369                              <1>         ;jna	L5
   370                              <1> 	;jmp	L13
   371                              <1> 	; 02/01/2022
   372 0000014E 7703                <1> 	ja	short L9_10
   373 00000150 E972FF              <1> 	jmp	L5
   374                              <1> L9_10:
   375 00000153 E90501              <1>         jmp     L13
   376                              <1> L10:
   377 00000156 FEC2                <1> 	inc 	dl
   378                              <1> 	; 25/12/2014
   379 00000158 8816[EB65]          <1> 	mov	[drv], dl
   380 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   381 0000015E CD13                <1> 	int	13h	; (conventional function)
   382                              <1> 	;jc	L13
   383                              <1> 	; 02/01/2022
   384 00000160 72F1                <1> 	jc	short L9_10
   385                              <1> 	; 14/01/2015
   386 00000162 8A16[EB65]          <1> 	mov	dl, [drv]
   387 00000166 52                  <1> 	push	dx
   388 00000167 51                  <1> 	push	cx
   389 00000168 E8FE00              <1> 	call	set_disk_parms
   390 0000016B 59                  <1> 	pop	cx
   391 0000016C 5A                  <1> 	pop	dx
   392                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   393                              <1> 	; 04/02/2016 (esi -> si)
   394                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   395                              <1> 	;		 ; at the '_end' of kernel.
   396                              <1> 	;mov	word [si], 30
   397                              <1> 	; 06/07/2016
   398 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   399                              <1> 	; 09/07/2016
   400 00000170 B81E00              <1> 	mov	ax, 001Eh
   401 00000173 8824                <1> 	mov	[si], ah ; 0
   402 00000175 46                  <1> 	inc	si
   403 00000176 8904                <1> 	mov	word [si], ax
   404                              <1>  	; word [si] = 30
   405                              <1> 	;
   406 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   407 0000017A CD13                <1> 	int	13h
   408                              <1>         ;jc	L13
   409                              <1> 	; 02/01/2022
   410 0000017C 72D5                <1> 	jc	short L9_10
   411                              <1> 	; 04/02/2016 (ebx -> bx)
   412                              <1> 	; 14/01/2015
   413                              <1> 	;sub	bx, bx
   414 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   415 00000180 88D3                <1> 	mov	bl, dl
   416 00000182 80EB80              <1> 	sub	bl, 80h
   417 00000185 81C3[F065]          <1> 	add	bx, hd0_type
   418 00000189 8A07                <1> 	mov 	al, [bx]
   419 0000018B 0C80                <1> 	or	al, 80h
   420 0000018D 8807                <1> 	mov 	[bx], al	
   421 0000018F 81EB[EE65]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   422 00000193 81C3[3A66]          <1> 	add	bx, drv.status
   423 00000197 8807                <1> 	mov	[bx], al
   424                              <1> 	; 04/02/2016 (eax -> ax)
   425 00000199 8B4410              <1> 	mov	ax, [si+16]
   426 0000019C 854412              <1> 	test	ax, [si+18]
   427 0000019F 7413                <1> 	jz	short L10_A0h 
   428                              <1> 			; 'CHS only' disks on EDD system 
   429                              <1> 			;  are reported with ZERO disk size
   430 000001A1 81EB[3A66]          <1> 	sub	bx, drv.status
   431 000001A5 C1E302              <1> 	shl	bx, 2
   432 000001A8 81C3[1E66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   433 000001AC 8907                <1> 	mov	[bx], ax
   434 000001AE 8B4412              <1> 	mov	ax, [si+18]
   435                              <1> 	;mov	[bx], ax
   436                              <1> 	; 02/01/2022 (BugFix)
   437 000001B1 894702              <1> 	mov	[bx+2], ax
   438                              <1> 
   439                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   440                              <1> 	 ; for CHS disks (28/02/2015)
   441                              <1> 	; 30/12/2014
   442 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   443 000001B7 88D0                <1> 	mov	al, dl
   444 000001B9 83E003              <1> 	and 	ax, 3
   445 000001BC C0E005              <1> 	shl	al, 5 ; *32
   446 000001BF 01C7                <1> 	add 	di, ax
   447 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   448 000001C4 8EC0                <1> 	mov	es, ax
   449                              <1> 	;
   450 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   451 000001C8 88CC                <1> 	mov	ah, cl	
   452 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   453 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   454 000001CE AB                  <1> 	stosw		
   455 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   456 000001D1 FEC0                <1> 	inc	al
   457 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   458 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   459 000001D6 AA                  <1> 	stosb
   460 000001D7 8A440C              <1> 	mov	al, [si+12]
   461 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   462 000001DB 31C0                <1>  	xor	ax, ax
   463                              <1> 	;dec	ax	 ; 02/01/2015 
   464 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   465                              <1> 	;xor	al, al	 ; 02/01/2015	
   466 000001DE AA                  <1> 	stosb		 ; reserved
   467 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   468                              <1> 		         ; (do not disable retries, 
   469                              <1> 			 ; more than 8 heads)
   470 000001E1 AA                  <1> 	stosb
   471 000001E2 8B4404              <1> 	mov	ax, [si+4]
   472 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   473                              <1> 	;push	ax	 ; 02/01/2015
   474 000001E6 8A4408              <1> 	mov	al, [si+8]
   475 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   476 000001EA 29C0                <1> 	sub 	ax, ax
   477                              <1> 	;pop	ax	 ; 02/01/2015	
   478 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   479 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   480 000001EF 243F                <1> 	and 	al, 3Fh	
   481 000001F1 AA                  <1> 	stosb
   482                              <1> 	;sub	al, al	 ; checksum
   483                              <1> 	;stosb
   484                              <1> 	;
   485 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   486 000001F5 AD                  <1> 	lodsw
   487 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   488 000001F7 AD                  <1> 	lodsw
   489 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   490                              <1> 	;
   491                              <1> 	; checksum calculation
   492 000001F9 89FE                <1> 	mov	si, di
   493 000001FB 06                  <1> 	push	es
   494 000001FC 1F                  <1> 	pop	ds
   495                              <1> 	;mov	cx, 16
   496 000001FD B90F00              <1> 	mov 	cx, 15
   497 00000200 29CE                <1> 	sub	si, cx
   498 00000202 30E4                <1> 	xor	ah, ah
   499                              <1> 	;del	cl
   500                              <1> L11:		
   501 00000204 AC                  <1> 	lodsb
   502 00000205 00C4                <1> 	add	ah, al
   503 00000207 E2FB                <1> 	loop	L11
   504                              <1> 	;
   505 00000209 88E0                <1> 	mov	al, ah
   506 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   507 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   508                              <1> 	;
   509 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   510 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   511                              <1> 	;
   512                              <1> 	; 23/02/2015
   513 00000210 57                  <1> 	push	di
   514                              <1> 	; ES:DI points to DPTE (FDPTE) location
   515                              <1> 	;mov	cx, 8
   516 00000211 B108                <1> 	mov	cl, 8
   517 00000213 F3A5                <1> 	rep	movsw	
   518                              <1> 	;
   519                              <1> 	; 23/02/2015
   520                              <1> 	; (P)ATA drive and LBA validation
   521                              <1> 	; (invalidating SATA drives and setting
   522                              <1> 	; CHS type I/O for old type fixed disks)
   523 00000215 5B                  <1> 	pop	bx
   524 00000216 8CC8                <1> 	mov	ax, cs
   525 00000218 8ED8                <1> 	mov	ds, ax
   526 0000021A 268B07              <1> 	mov	ax, [es:bx]
   527 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   528 00000220 7418                <1> 	je	short L11a
   529 00000222 3D7001              <1> 	cmp	ax, 170h
   530 00000225 7413                <1> 	je	short L11a
   531                              <1> 	; invalidation 
   532                              <1> 	; (because base port address is not 1F0h or 170h)
   533 00000227 30FF                <1> 	xor	bh, bh
   534 00000229 88D3                <1> 	mov	bl, dl
   535 0000022B 80EB80              <1> 	sub	bl, 80h
   536 0000022E C687[F065]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   537 00000233 808F[3C66]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   538 00000238 EB14                <1> 	jmp	short L11b
   539                              <1> L11a:	
   540                              <1> 	; LBA validation
   541 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   542 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   543 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   544                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   545 00000242 28FF                <1> 	sub	bh, bh
   546 00000244 88D3                <1> 	mov	bl, dl
   547 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   548 00000249 80A7[3C66]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   549                              <1> 				; bit 0 = LBA ready bit
   550                              <1> 	; 'diskio' procedure will check this bit !
   551                              <1> L11b:
   552 0000024E 3A16[EC65]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   553 00000252 7307                <1>         jnb     short L13
   554 00000254 E9FFFE              <1>         jmp     L10
   555                              <1> L12:
   556                              <1> 	; Restore data registers
   557 00000257 8CC8                <1> 	mov	ax, cs
   558 00000259 8ED8                <1> 	mov	ds, ax	
   559                              <1> L13:
   560                              <1> 	; 13/12/2014
   561 0000025B 0E                  <1> 	push	cs
   562 0000025C 07                  <1> 	pop	es
   563                              <1> L14:
   564 0000025D B411                <1> 	mov 	ah, 11h
   565 0000025F CD16                <1> 	int 	16h
   566                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   567                              <1> 	; 02/01/2022
   568 00000261 7466                <1> 	jz	short L16
   569 00000263 B010                <1> 	mov	al, 10h
   570 00000265 CD16                <1> 	int 	16h
   571 00000267 EBF4                <1> 	jmp 	short L14
   572                              <1> L15:
   573                              <1> 
   574                              <1> ; //////
   575                              <1> 
   576                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   577                              <1> %if 0
   578                              <1> 	; 24/11/2014
   579                              <1> 	; 19/11/2014
   580                              <1> 	; 14/11/2014
   581                              <1> 	; Temporary code for disk searching code check
   582                              <1> 	;
   583                              <1> 	; This code will show existing (usable) drives and also
   584                              <1> 	; will show EDD interface support status for hard disks		
   585                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   586                              <1> 	; no need to get it again in protected mode...) 
   587                              <1> 	;	
   588                              <1> 	; 13/11/2014
   589                              <1> 	mov	bx, 7
   590                              <1> 	mov	ah, 0Eh
   591                              <1> 	mov	al, [fd0_type]
   592                              <1> 	and	al, al
   593                              <1> 	jz	short L15a
   594                              <1> 	mov	dl, al
   595                              <1> 	mov	al, 'F'
   596                              <1> 	int 	10h
   597                              <1> 	mov	al, 'D'
   598                              <1> 	int 	10h
   599                              <1> 	mov	al, '0'
   600                              <1> 	int 	10h
   601                              <1> 	mov	al, ' '
   602                              <1> 	int	10h
   603                              <1> 	call	L15c
   604                              <1> 	mov	al, ' '
   605                              <1> 	int	10h
   606                              <1> 	;
   607                              <1> 	mov	al, [fd1_type]
   608                              <1> 	and	al, al
   609                              <1> 	jz	short L15a
   610                              <1> 	mov	dl, al
   611                              <1> 	mov	al, 'F'
   612                              <1> 	int 	10h
   613                              <1> 	mov	al, 'D'
   614                              <1> 	int 	10h
   615                              <1> 	mov	al, '1'
   616                              <1> 	int 	10h
   617                              <1> 	mov	al, ' '
   618                              <1> 	int	10h
   619                              <1> 	call	L15c
   620                              <1> 	mov	al, ' '
   621                              <1> 	int	10h
   622                              <1> 	mov	al, ' '
   623                              <1> 	int	10h
   624                              <1> L15a:
   625                              <1> 	mov	al, [hd0_type]
   626                              <1> 	and	al, al
   627                              <1> 	jz	short L15b
   628                              <1> 	mov	dl, al
   629                              <1> 	mov	al, 'H'
   630                              <1> 	int 	10h
   631                              <1> 	mov	al, 'D'
   632                              <1> 	int 	10h
   633                              <1> 	mov	al, '0'
   634                              <1> 	int 	10h
   635                              <1> 	mov	al, ' '
   636                              <1> 	int 	10h
   637                              <1> 	call	L15c
   638                              <1> 	mov	al, ' '
   639                              <1> 	int	10h
   640                              <1> 	;
   641                              <1> 	mov	al, [hd1_type]
   642                              <1> 	and	al, al
   643                              <1> 	jz	short L15b
   644                              <1> 	mov	dl, al
   645                              <1> 	mov	al, 'H'
   646                              <1> 	int 	10h
   647                              <1> 	mov	al, 'D'
   648                              <1> 	int 	10h
   649                              <1> 	mov	al, '1'
   650                              <1> 	int 	10h
   651                              <1> 	mov	al, ' '
   652                              <1> 	int 	10h
   653                              <1> 	call	L15c
   654                              <1> 	mov	al, ' '
   655                              <1> 	int	10h
   656                              <1> 	;
   657                              <1> 	mov	al, [hd2_type]
   658                              <1> 	and	al, al
   659                              <1> 	jz	short L15b
   660                              <1> 	mov	dl, al
   661                              <1> 	mov	al, 'H'
   662                              <1> 	int 	10h
   663                              <1> 	mov	al, 'D'
   664                              <1> 	int 	10h
   665                              <1> 	mov	al, '2'
   666                              <1> 	int 	10h
   667                              <1> 	mov	al, ' '
   668                              <1> 	int 	10h
   669                              <1> 	call	L15c
   670                              <1> 	mov	al, ' '
   671                              <1> 	int	10h
   672                              <1> 	;
   673                              <1> 	mov	al, [hd3_type]
   674                              <1> 	and	al, al
   675                              <1> 	jz	short L15b
   676                              <1> 	mov	dl, al
   677                              <1> 	mov	al, 'H'
   678                              <1> 	int 	10h
   679                              <1> 	mov	al, 'D'
   680                              <1> 	int 	10h
   681                              <1> 	mov	al, '3'
   682                              <1> 	int 	10h
   683                              <1> 	mov	al, ' '
   684                              <1> 	int 	10h
   685                              <1> 	call	L15c
   686                              <1> 	mov	al, ' '
   687                              <1> 	int	10h
   688                              <1> 	;
   689                              <1> L15b:
   690                              <1> 	mov	al, 0Dh
   691                              <1> 	int 	10h	
   692                              <1> 	mov	al, 0Ah
   693                              <1> 	int 	10h
   694                              <1> 	;;xor	ah, ah
   695                              <1> 	;;int 	16h	
   696                              <1> 	;
   697                              <1>         ;jmp	L16  ; jmp short L16
   698                              <1>         ; 02/01/2022
   699                              <1> 	jmp	short L16
   700                              <1> 	;
   701                              <1> L15c:
   702                              <1> 	mov	dh, dl
   703                              <1> 	shr	dh, 4
   704                              <1> 	add	dh, 30h
   705                              <1> 	and	dl, 15
   706                              <1> 	add	dl, 30h
   707                              <1> 	mov	al, dh
   708                              <1> 	int	10h
   709                              <1> 	mov	al, dl
   710                              <1> 	int	10h
   711                              <1> 	retn
   712                              <1> 	;
   713                              <1> 	; end of temporary code for disk searching code check
   714                              <1> 
   715                              <1> %endif
   716                              <1> 
   717                              <1> ; //////
   718                              <1> 
   719                              <1> set_disk_parms:
   720                              <1> 	; 04/02/2016 (ebx -> bx)
   721                              <1> 	; 10/07/2015
   722                              <1> 	; 14/01/2015
   723                              <1> 	;push	bx
   724 00000269 28FF                <1> 	sub	bh, bh
   725 0000026B 8A1E[EB65]          <1> 	mov	bl, [drv]
   726 0000026F 80FB80              <1> 	cmp	bl, 80h
   727 00000272 7203                <1> 	jb	short sdp0
   728 00000274 80EB7E              <1> 	sub	bl, 7Eh
   729                              <1> sdp0:	
   730 00000277 81C3[3A66]          <1> 	add	bx, drv.status
   731 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   732                              <1> 	;
   733 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   734 00000280 88CC                <1> 	mov	ah, cl ; 
   735 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   736 00000285 81EB[3A66]          <1> 	sub	bx, drv.status
   737 00000289 D0E3                <1> 	shl	bl, 1
   738 0000028B 81C3[F465]          <1> 	add	bx, drv.cylinders
   739 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   740 00000290 8907                <1> 	mov	[bx], ax
   741 00000292 50                  <1> 	push	ax ; ** cylinders
   742 00000293 81EB[F465]          <1> 	sub	bx, drv.cylinders
   743 00000297 81C3[0266]          <1> 	add	bx, drv.heads
   744 0000029B 30E4                <1> 	xor	ah, ah
   745 0000029D 88F0                <1> 	mov	al, dh ; heads
   746 0000029F 40                  <1> 	inc	ax
   747 000002A0 8907                <1> 	mov	[bx], ax
   748 000002A2 81EB[0266]          <1>         sub     bx, drv.heads
   749 000002A6 81C3[1066]          <1>         add     bx, drv.spt
   750 000002AA 30ED                <1> 	xor	ch, ch
   751 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   752 000002AF 890F                <1> 	mov	[bx], cx
   753 000002B1 81EB[1066]          <1>         sub     bx, drv.spt
   754 000002B5 D1E3                <1> 	shl	bx, 1
   755 000002B7 81C3[1E66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   756                              <1> 	; LBA size = cylinders * heads * secpertrack
   757 000002BB F7E1                <1> 	mul	cx 
   758 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   759 000002BF 58                  <1> 	pop	ax ; ** cylinders
   760 000002C0 48                  <1> 	dec	ax ; 1 cylinder reserved (!?)
   761 000002C1 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   762 000002C3 8907                <1> 	mov	[bx], ax
   763 000002C5 895702              <1> 	mov	[bx+2], dx
   764                              <1> 	;
   765                              <1> 	;pop	bx
   766 000002C8 C3                  <1> 	retn
   767                              <1> 
   768                              <1> ;align 2
   769                              <1> 
   770                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   771                              <1> ;heads	  :  dw 0, 0, 0, 0, 0, 0
   772                              <1> ;spt	  :  dw 0, 0, 0, 0, 0, 0
   773                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   774                              <1> 
   775                              <1> ;last_drv:
   776                              <1> ;	db  0
   777                              <1> ;drv_status:
   778                              <1> ;	db  0,0,0,0,0,0
   779                              <1> ;	db 0
   780                              <1> 
   781                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   782                              <1> 
   783                              <1> L16:
   219                                  
   220                                  	; 10/11/2014
   221 000002C9 FA                           	cli	; Disable interrupts (clear interrupt flag)
   222                                  		; Reset Interrupt MASK Registers (Master&Slave)
   223                                  	;mov	al, 0FFh	; mask off all interrupts
   224                                  	;out	21h, al		; on master PIC (8259)
   225                                  	;jmp 	$+2  ; (delay)
   226                                  	;out	0A1h, al	; on slave PIC (8259)
   227                                  	;
   228                                  	; Disable NMI 
   229 000002CA B080                    	mov   	al, 80h 
   230 000002CC E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   231                                  	;23/02/2015
   232 000002CE 90                      	nop			;
   233                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   234                                  				; for preventing unknown state (!?)
   235                                  
   236                                  	; 02/01/2022
   237                                  	%define KERNELFSIZE KEND-KSTART 
   238                                  	;
   239                                   	; 20/08/2014
   240                                  	; Moving the kernel 64 KB back (to physical address 0)
   241                                  	; DS = CS = 1000h
   242                                  	; 05/11/2014
   243 000002CF 31C0                    	xor	ax, ax
   244 000002D1 8EC0                    	mov	es, ax ; ES = 0
   245                                  	;
   246                                  	;;mov	cx, (KEND - KLOAD)/4
   247                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 02/01/2022
   248 000002D3 B94634                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   249 000002D6 31F6                    	xor	si, si
   250 000002D8 31FF                    	xor	di, di
   251                                  	;rep	movsd
   252 000002DA F3A5                    	rep	movsw ; 02/01/2022
   253                                  	;
   254 000002DC 06                      	push	es ; 0
   255 000002DD 68[E102]                	push	L17
   256 000002E0 CB                      	retf
   257                                  	;
   258                                  L17:
   259                                  	; Turn off the floppy drive motor
   260 000002E1 BAF203                          mov     dx, 3F2h
   261 000002E4 EE                              out     dx, al ; 0 ; 31/12/2013
   262                                  
   263                                  	; Enable access to memory above one megabyte
   264                                  L18:
   265 000002E5 E464                    	in	al, 64h
   266 000002E7 A802                    	test	al, 2
   267 000002E9 75FA                            jnz     short L18
   268 000002EB B0D1                    	mov	al, 0D1h	; Write output port
   269 000002ED E664                    	out	64h, al
   270                                  L19:
   271 000002EF E464                    	in	al, 64h
   272 000002F1 A802                    	test	al, 2
   273 000002F3 75FA                            jnz     short L19
   274 000002F5 B0DF                    	mov	al, 0DFh	; Enable A20 line
   275 000002F7 E660                    	out	60h, al
   276                                  ;L20:
   277                                  	;
   278                                  	; Load global descriptor table register
   279                                  
   280                                          ;mov     ax, cs
   281                                          ;mov     ds, ax
   282                                  
   283 000002F9 2E0F0116[1063]                  lgdt    [cs:gdtd]
   284                                  
   285 000002FF 0F20C0                          mov     eax, cr0
   286                                  	; or 	eax, 1
   287 00000302 40                      	inc     ax
   288 00000303 0F22C0                  	mov     cr0, eax
   289                                  
   290                                  	; Jump to 32 bit code
   291                                  	
   292 00000306 66                      	db 66h 			; Prefix for 32-bit
   293 00000307 EA                      	db 0EAh 		; Opcode for far jump
   294 00000308 [0E030000]              	dd StartPM 		; Offset to start, 32-bit
   295                                  				; (1000h:StartPM = StartPM + 10000h)
   296 0000030C 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   297                                  				; assuming that StartPM resides in code32
   298                                  
   299                                  [BITS 32] 
   300                                  
   301                                  StartPM:
   302                                  	; Kernel Base Address = 0 ; 30/12/2013
   303 0000030E 66B81000                	mov ax, KDATA           ; Save data segment identifier
   304 00000312 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   305 00000314 8EC0                           	mov es, ax              ; Move data segment into ES register
   306 00000316 8EE0                           	mov fs, ax              ; Move data segment into FS register
   307 00000318 8EE8                          	mov gs, ax              ; Move data segment into GS register
   308 0000031A 8ED0                            mov ss, ax              ; Move data segment into SS register
   309 0000031C BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   310                                  
   311                                  clear_bss: ; Clear uninitialized data area
   312                                  	; 11/03/2015
   313 00000321 31C0                    	xor	eax, eax ; 0
   314                                  	;mov	ecx, (bss_end - bss_start)/4
   315                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   316                                  	; 02/01/2022
   317 00000323 B9BC050000              	mov	ecx, BSS_SIZE/4
   318 00000328 BF[90680000]            	mov	edi, bss_start
   319 0000032D F3AB                    	rep	stosd  		
   320                                  
   321                                  memory_init:
   322                                  	; Initialize memory allocation table and page tables
   323                                  	;
   324                                  	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   325                                  	; 16/11/2014
   326                                  	; 15/11/2014
   327                                  	; 07/11/2014
   328                                  	; 06/11/2014
   329                                  	; 05/11/2014
   330                                  	; 04/11/2014
   331                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   332                                  	;
   333                                  ;	xor	eax, eax
   334                                  ;	xor 	ecx, ecx
   335 0000032F B108                    	mov	cl, 8
   336 00000331 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   337 00000336 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   338                                  				   ; for the first 1 MB memory
   339                                  	;
   340 00000338 8B0D[84680000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   341                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   342                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   343                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   344 0000033E C1E902                  	shr	ecx, 2	; 02/01/2022
   345 00000341 890D[006B0000]          	mov	[free_pages], ecx
   346 00000347 8B15[88680000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   347                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   348                                  				   ; between 16 MB and 4 GB.
   349                                  	;or	dx, dx
   350 0000034D 09D2                    	or	edx, edx ; 02/01/2022
   351 0000034F 7412                    	jz	short mi_0
   352                                  	;
   353                                  	;mov	ax, dx
   354 00000351 89D0                    	mov	eax, edx ; 02/01/2022
   355 00000353 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   356 00000356 0105[006B0000]          	add	[free_pages], eax
   357 0000035C 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   358 00000361 EB06                    	jmp	short mi_1
   359                                  mi_0:
   360                                  	;mov	ax, cx
   361 00000363 89C8                    	mov	eax, ecx ; 02/01/2022	 
   362 00000365 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   363                                  mi_1:
   364 00000369 A3[FC6A0000]            	mov	[memory_size], eax ; Total available memory in pages
   365                                  				   ; 1 alloc. tbl. bit = 1 memory page
   366                                  				   ; 32 allocation bits = 32 mem. pages
   367                                  	;
   368 0000036E 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   369 00000373 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   370                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   371                                  				   ;  --> x M.A.T. pages, if y = 0
   372                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   373 00000376 A3[106B0000]            	mov	[mat_size], eax ; 02/01/2022
   374 0000037B C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   375                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   376 0000037E 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   377                                  	; Set/Calculate Kernel's Page Directory Address
   378 00000380 81C300001000            	add	ebx, MEM_ALLOC_TBL
   379 00000386 891D[F86A0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   380                                  				   ; just after the last M.A.T. page
   381                                  	;
   382 0000038C 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   383 0000038F A3[086B0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   384                                  	;			   ; (allocation status search must be
   385                                  				   ; stopped after here)
   386 00000394 31C0                    	xor	eax, eax
   387 00000396 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   388                                  	;push	cx
   389 00000397 51                      	push	ecx ; 02/01/2022 
   390 00000398 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   391                                  				   ; count of 32 allocation bits
   392 0000039B F3AB                    	rep	stosd
   393                                  	;pop	cx
   394 0000039D 59                      	pop	ecx ; 02/01/2022
   395 0000039E 40                      	inc	eax		   ; 0
   396 0000039F 80E11F                  	and	cl, 31		   ; remain bits
   397 000003A2 7412                    	jz	short mi_4
   398 000003A4 8907                    	mov	[edi], eax	   ; reset
   399                                  mi_2:
   400 000003A6 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   401 000003A9 FEC9                    	dec	cl
   402 000003AB 7404                    	jz	short mi_3
   403 000003AD FEC0                    	inc	al
   404 000003AF EBF5                    	jmp	short mi_2
   405                                  mi_3:
   406 000003B1 28C0                    	sub	al, al	   	   ; 0
   407 000003B3 83C704                  	add	edi, 4		   ; 15/11/2014
   408                                  mi_4:
   409 000003B6 09D2                    	or	edx, edx ; 02/01/2022
   410                                  	;or	dx, dx		  ; check 16M to 4G memory space
   411 000003B8 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   412                                  	;	
   413 000003BA B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   414                                  	;	
   415 000003BF 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   416 000003C1 7405                    	jz	short mi_5	  ; jump if EDI points to 
   417                                  				  ;         end of first 16 MB	
   418                                  	;shr	ecx, 1		  ; convert to dword count
   419                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   420 000003C3 C1E902                  	shr	ecx, 2	; 02/01/2022
   421 000003C6 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   422                                  				  ; (memory hole under 16 MB)
   423                                  mi_5:
   424 000003C8 89D1                    	mov	ecx, edx ; 02/01/2022
   425                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   426 000003CA D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   427 000003CC 9C                      	pushf			  ; 16/11/2014		
   428 000003CD 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   429 000003CE F3AB                    	rep	stosd
   430 000003D0 40                      	inc	eax		  ; 0
   431 000003D1 9D                      	popf			  ; 16/11/2014
   432 000003D2 7305                    	jnc	short mi_6
   433 000003D4 6648                    	dec	ax		  ; eax = 0000FFFFh
   434 000003D6 AB                      	stosd
   435 000003D7 6640                    	inc	ax		  ; 0		
   436                                  mi_6:
   437 000003D9 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   438 000003DB 7309                    	jnb	short mi_7	  ; end of memory allocation table
   439                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   440 000003DD 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   441 000003DF 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   442                                  	;shr	ecx, 1		  ; to dword count
   443                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   444 000003E1 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   445 000003E4 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   446                                  mi_7:
   447                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   448 000003E6 BA00001000              	mov	edx, MEM_ALLOC_TBL
   449                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   450                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   451 000003EB 8B0D[106B0000]          	mov	ecx, [mat_size] ; 02/01/2022
   452                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   453 000003F1 89D7                    	mov	edi, edx
   454 000003F3 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   455                                  				  ; byte offset in M.A.T.
   456                                  				  ; (1 M.A.T. byte points to 
   457                                  				  ;	      32768 bytes)
   458                                  				  ; Note: MEM_ALLOC_TBL address 
   459                                  				  ; must be aligned on 128 KB 
   460                                  				  ; boundary!
   461 000003F6 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   462                                  	; eax = 0
   463 000003F8 290D[006B0000]          	sub	[free_pages], ecx ; 07/11/2014
   464                                  mi_8:
   465 000003FE 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   466                                  	;dec	bl
   467 00000401 FEC9                    	dec	cl
   468 00000403 7404                    	jz	short mi_9
   469 00000405 FEC0                    	inc	al
   470 00000407 EBF5                    	jmp	short mi_8
   471                                  mi_9:
   472                                  	;
   473                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   474                                  	;		(allocate pages for system page tables)
   475                                  
   476                                  	; edx = MEM_ALLOC_TBL
   477 00000409 8B0D[FC6A0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   478 0000040F 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   479 00000415 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   480                                  				 ; page table count (PDE count)
   481                                  	;
   482 00000418 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   483                                  	;
   484 00000419 41                      	inc	ecx		 ; +1 for kernel page directory	
   485                                  	;
   486 0000041A 290D[006B0000]          	sub	[free_pages], ecx ; 07/11/2014
   487                                  	;
   488 00000420 8B35[F86A0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   489 00000426 C1EE0C                  	shr	esi, 12		 ; convert to page number
   490                                  mi_10:
   491 00000429 89F0                    	mov	eax, esi	 ; allocation bit offset
   492 0000042B 89C3                    	mov	ebx, eax
   493 0000042D C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   494 00000430 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   495                                  				 ;   to align on dword boundary
   496 00000433 83E01F                  	and	eax, 31		 ; set allocation bit position 
   497                                  				 ;  (bit 0 to bit 31)
   498                                  	;
   499 00000436 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   500                                  	;
   501 00000438 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   502                                  	;
   503 0000043B 46                      	inc	esi		 ; next page table
   504 0000043C E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   505                                  				 ; (ecx = page table count + 1)
   506                                  	;
   507 0000043E 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   508                                  	;
   509                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   510                                  	;
   511                                  	; Initialize Kernel's Page Directory
   512 0000043F 8B3D[F86A0000]          	mov	edi, [k_page_dir]
   513 00000445 89F8                    	mov	eax, edi
   514 00000447 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   515                                  		     	      ; supervisor + read&write + present
   516 00000449 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   517                                  mi_11:
   518 0000044B 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   519                                  			        ; EAX points to next page table
   520 00000450 AB                      	stosd
   521 00000451 E2F8                    	loop	mi_11
   522 00000453 29C0                    	sub	eax, eax	; Empty PDE
   523                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   524                                  	; 02/01/2022
   525 00000455 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   526 00000457 29D1                    	sub	ecx, edx
   527 00000459 7402                    	jz	short mi_12
   528 0000045B F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   529                                  	;
   530                                  	; Initialization of Kernel's Page Directory is OK, here.
   531                                  mi_12:
   532                                  	; Initialize Kernel's Page Tables
   533                                  	;
   534                                  	; (EDI points to address of page table 0)
   535                                  	; eax = 0
   536 0000045D 8B0D[FC6A0000]          	mov	ecx, [memory_size] ; memory size in pages
   537 00000463 89CA                    	mov	edx, ecx	; (***)
   538 00000465 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   539                                  			     ; supervisor + read&write + present
   540                                  mi_13:
   541 00000467 AB                      	stosd
   542 00000468 0500100000              	add	eax, 4096	
   543 0000046D E2F8                    	loop	mi_13
   544                                  	; 02/01/2022
   545 0000046F 66B9FF03                	mov	cx, 1023
   546 00000473 21CA                    	and	edx, ecx
   547                                  	;and	dx, 1023	; (***)
   548 00000475 7407                    	jz	short mi_14
   549                                  	;mov	cx, 1024	
   550                                  	; 02/01/2022
   551                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   552 00000477 41                      	inc	ecx ; ecx = 1024
   553 00000478 29D1                    	sub	ecx, edx
   554                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   555 0000047A 31C0                    	xor	eax, eax
   556 0000047C F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   557                                  				; of the last page table
   558                                  mi_14:
   559                                  	;  Initialization of Kernel's Page Tables is OK, here.
   560                                  	;
   561 0000047E 89F8                    	mov	eax, edi	; end of the last page table page
   562                                  			        ; (beginging of user space pages)
   563 00000480 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   564 00000483 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   565                                  				; aligning on dword boundary
   566                                  	 
   567 00000485 A3[0C6B0000]            	mov	[first_page], eax
   568 0000048A A3[046B0000]            	mov	[next_page], eax ; The first free page pointer
   569                                  				 ; for user programs
   570                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   571                                  	;
   572                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   573                                  	;
   574                                  	
   575                                  	; Enable paging
   576                                  	;
   577 0000048F A1[F86A0000]                    mov     eax, [k_page_dir]
   578 00000494 0F22D8                  	mov	cr3, eax
   579 00000497 0F20C0                  	mov	eax, cr0
   580 0000049A 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   581 0000049F 0F22C0                  	mov	cr0, eax
   582                                          ;jmp    KCODE:StartPMP
   583                                  
   584 000004A2 EA                      	db 0EAh 		; Opcode for far jump
   585 000004A3 [A9040000]                      dd StartPMP		; 32 bit offset
   586 000004A7 0800                    	dw KCODE		; kernel code segment descriptor
   587                                  
   588                                  StartPMP:
   589                                  	; 06/11//2014
   590                                  	; Clear video page 0
   591                                  	;
   592                                  	; Temporary Code
   593                                  	;
   594                                  	;mov	ecx, 80*25/2
   595 000004A9 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   596 000004AD BF00800B00              	mov	edi, 0B8000h
   597 000004B2 57                      	push	edi ; * ; 02/01/2022
   598 000004B3 31C0                    	xor	eax, eax	; black background, black fore color
   599 000004B5 F3AB                    	rep	stosd
   600                                  	
   601                                  	; 19/08/2014
   602                                  	; Kernel Base Address = 0
   603                                  	; It is mapped to (physically) 0 in the page table.
   604                                  	; So, here is exactly 'StartPMP' address.
   605                                  	;
   606                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   607                                  	;;mov	esi, msgPM
   608                                  	;; 14/08/2015 (kernel version message will appear
   609                                  	;;	       when protected mode and paging is enabled)
   610 000004B7 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   611 000004B9 BE[50660000]            	mov	esi, msgKVER
   612 000004BE 5F                      	pop	edi ; * ; 02/01/2022
   613                                  	;mov	edi, 0B8000h ; 27/08/2014
   614                                  	; 20/08/2014
   615 000004BF E893010000              	call	printk
   616                                  
   617                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   618                                  	; // Set IRQ offsets
   619                                  	;
   620                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   621                                  	;
   622                                  					;; ICW1
   623 000004C4 B011                    	mov	al, 11h			; Initialization sequence
   624 000004C6 E620                    	out	20h, al			; 	8259A-1
   625                                  	; jmp 	$+2
   626 000004C8 E6A0                    	out	0A0h, al		; 	8259A-2
   627                                  					;; ICW2
   628 000004CA B020                    	mov	al, 20h			; Start of hardware ints (20h)
   629 000004CC E621                    	out	21h, al			;	for 8259A-1
   630                                  	; jmp 	$+2
   631 000004CE B028                    	mov	al, 28h			; Start of hardware ints (28h)
   632 000004D0 E6A1                    	out	0A1h, al		; 	for 8259A-2
   633                                  					;
   634 000004D2 B004                    	mov	al, 04h			;; ICW3
   635 000004D4 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   636                                  	; jmp 	$+2
   637 000004D6 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   638 000004D8 E6A1                    	out	0A1h, al		;
   639                                  					;; ICW4
   640 000004DA B001                    	mov	al, 01h	 		;
   641 000004DC E621                    	out	21h, al			; 	8086 mode, normal EOI	
   642                                  	; jmp 	$+2
   643 000004DE E6A1                    	out	0A1h, al		;	for both chips.
   644                                  
   645                                  	;mov	al, 0FFh	; mask off all interrupts for now
   646                                  	;out	21h, al
   647                                  	;; jmp 	$+2
   648                                  	;out	0A1h, al
   649                                  
   650                                  	; 02/04/2015
   651                                  	; 26/03/2015 System call (INT 30h) modification
   652                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   653                                  	;
   654                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   655                                  	;  setup_idt:
   656                                  	;
   657                                          ;; 16/02/2015
   658                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   659                                  	; 21/08/2014 (timer_int)
   660 000004E0 BE[1C630000]            	mov	esi, ilist
   661 000004E5 8D3D[90680000]          	lea	edi, [idt]
   662                                  	; 26/03/2015
   663 000004EB B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   664                                  	; 02/04/2015
   665 000004F0 BB00000800              	mov	ebx,  80000h
   666                                  rp_sidt1:
   667 000004F5 AD                      	lodsd
   668 000004F6 89C2                    	mov	edx, eax
   669 000004F8 66BA008E                	mov	dx, 8E00h
   670 000004FC 6689C3                  	mov	bx, ax
   671 000004FF 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   672                                         			        ; /* interrupt gate - dpl=0, present */
   673 00000501 AB                      	stosd	; selector & offset bits 0-15 	
   674 00000502 89D0                    	mov	eax, edx
   675 00000504 AB                      	stosd	; attributes & offset bits 16-23
   676 00000505 E2EE                    	loop	rp_sidt1
   677 00000507 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   678                                  rp_sidt2:
   679 00000509 AD                      	lodsd
   680 0000050A 21C0                    	and	eax, eax
   681 0000050C 7413                    	jz	short rp_sidt3
   682 0000050E 89C2                    	mov	edx, eax
   683 00000510 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   684 00000514 6689C3                  	mov	bx, ax
   685 00000517 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   686 00000519 AB                      	stosd
   687 0000051A 89D0                    	mov	eax, edx
   688 0000051C AB                      	stosd
   689 0000051D E2EA                    	loop	rp_sidt2
   690 0000051F EB16                    	jmp	short sidt_OK
   691                                  rp_sidt3:
   692 00000521 B8[7B090000]            	mov	eax, ignore_int
   693 00000526 89C2                    	mov	edx, eax
   694 00000528 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   695 0000052C 6689C3                  	mov	bx, ax
   696 0000052F 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   697                                  rp_sidt4:
   698 00000531 AB                      	stosd
   699 00000532 92                      	xchg	eax, edx
   700 00000533 AB                      	stosd
   701 00000534 92                      	xchg	edx, eax
   702 00000535 E2FA                    	loop	rp_sidt4
   703                                  sidt_OK: 
   704 00000537 0F011D[16630000]        	lidt 	[idtd]
   705                                  	;
   706                                  	; TSS descriptor setup ; 24/03/2015
   707 0000053E B8[906A0000]            	mov	eax, task_state_segment
   708 00000543 66A3[0A630000]          	mov	[gdt_tss0], ax
   709 00000549 C1C010                  	rol	eax, 16
   710 0000054C A2[0C630000]            	mov	[gdt_tss1], al
   711 00000551 8825[0F630000]          	mov	[gdt_tss2], ah
   712 00000557 66C705[F66A0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   712 0000055F 00                 
   713                                  		; 
   714                                  		; IO Map Base address (When this address points
   715                                  		; to end of the TSS, CPU does not use IO port 
   716                                  		; permission bit map for RING 3 IO permissions, 
   717                                  		; access to any IO ports in ring 3 will be forbidden.)
   718                                   		;
   719                                  	;mov	[tss.esp0], esp ; TSS offset 4
   720                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   721 00000560 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   722                                  			 ; occurs (or a system call -software INT- is requested)
   723                                  			 ; while cpu running in ring 3 (in user mode).				
   724                                  			 ; (Kernel stack pointer and segment will be loaded
   725                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   726 00000564 0F00D8                  	ltr	ax  ; Load task register
   727                                  	;
   728                                  esp0_set0:
   729                                  	; 30/07/2015
   730 00000567 8B0D[FC6A0000]          	mov 	ecx, [memory_size] ; memory size in pages
   731 0000056D C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   732 00000570 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   733                                  			  ; (kernel mode virtual address)
   734 00000576 7605                    	jna	short esp0_set1
   735                                  	;
   736                                  	; If available memory > CORE (end of the 1st 4 MB)
   737                                  	; set stack pointer to CORE
   738                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   739                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   740 00000578 B900004000              	mov	ecx, CORE
   741                                  esp0_set1:
   742 0000057D 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   743                                  esp0_set_ok:
   744                                  	; 30/07/2015 (**tss.esp0**) 
   745 0000057F 8925[946A0000]          	mov	[tss.esp0], esp
   746 00000585 66C705[986A0000]10-             mov     word [tss.ss0], KDATA
   746 0000058D 00                 
   747                                  	; 14/08/2015
   748                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   749                                  	;
   750                                  	;cli	; Disable interrupts (for CPU)
   751                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   752                                  	;
   753 0000058E 30C0                    	xor	al, al		; Enable all hardware interrupts!
   754 00000590 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   755 00000592 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   756 00000594 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   757                                  				; (Even if related hardware component
   758                                  				;  does not exist!)
   759                                  	; Enable NMI 
   760 00000596 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   761 00000598 E670                    	out  	70h, al
   762                                  	; 23/02/2015
   763 0000059A 90                      	nop
   764 0000059B E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   765                                  				; for preventing unknown state (!?)
   766                                  	;
   767                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   768                                  	;
   769                                  	; 02/09/2014
   770 0000059D 6631DB                  	xor	bx, bx
   771 000005A0 66BA0002                	mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   772 000005A4 E8280F0000              	call	set_cpos
   773                                  	;
   774                                  	; 06/11/2014
   775                                  	; Temporary Code
   776                                  	;
   777 000005A9 E8A1100000              	call	memory_info
   778                                  	; 14/08/2015
   779                                  	;call getch ; 28/02/2015
   780                                  drv_init:
   781 000005AE FB                      	sti	; Enable Interrupts 
   782                                  	; 06/02/2015
   783 000005AF 8B15[F0650000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   784 000005B5 668B1D[EE650000]        	mov	bx, [fd0_type] ; fd0, fd1
   785                                  	; 22/02/2015
   786 000005BC 6621DB                  	and	bx, bx
   787 000005BF 751B                    	jnz	short di1
   788                                  	;
   789 000005C1 09D2                    	or 	edx, edx
   790 000005C3 7529                    	jnz	short di2
   791                                  	;
   792                                  setup_error:
   793 000005C5 BE[39670000]            	mov 	esi, setup_error_msg
   794                                  psem:	
   795 000005CA AC                      	lodsb
   796 000005CB 08C0                    	or	al, al
   797                                  	;jz	short haltx ; 22/02/2015
   798 000005CD 7426                    	jz	short di3
   799 000005CF 56                      	push	esi
   800 000005D0 31DB                    	xor	ebx, ebx ; 0
   801                                  			; Video page 0 (bl=0)
   802 000005D2 B407                    	mov	ah, 07h ; Black background, 
   803                                  			; light gray forecolor
   804 000005D4 E8EE0D0000              	call	write_tty
   805 000005D9 5E                      	pop	esi
   806 000005DA EBEE                    	jmp	short psem
   807                                  
   808                                  di1:
   809                                  	; supress 'jmp short T6'
   810                                  	;  (activate fdc motor control code)
   811 000005DC 66C705[D8060000]90-     	mov	word [T5], 9090h ; nop
   811 000005E4 90                 
   812                                  	;
   813                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   814                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   815                                  	;stosw
   816                                  	;mov 	ax, cs
   817                                  	;stosw
   818                                  	;; 16/02/2015
   819                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   820                                  	;
   821 000005E5 E8761F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   822                                  	;
   823 000005EA 09D2                    	or	edx, edx
   824 000005EC 7407                            jz      short di3
   825                                  di2:
   826 000005EE E8B31F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   827 000005F3 72D0                            jc      short setup_error
   828                                  di3:
   829 000005F5 E829100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   830                                  	;
   831 000005FA E8365C0000              	call	display_disks ; 07/03/2015  (Temporary)
   832                                  ;haltx:
   833                                  	; 14/08/2015
   834                                  	;call	getch ; 22/02/2015
   835 000005FF FB                      	sti	; Enable interrupts (for CPU)
   836                                  	; 14/08/2015
   837                                  	;mov 	ecx, 0FFFFFFFh
   838                                  	; 24/12/2021
   839 00000600 B9FFFF2F00              	mov 	ecx, 02FFFFFh
   840                                  md_info_msg_wait:
   841 00000605 51                      	push 	ecx
   842 00000606 B001                    	mov	al, 1
   843 00000608 8A25[266B0000]          	mov 	ah, [ptty] ; active (current) video page
   844 0000060E E86B590000              	call	getc_n
   845 00000613 59                      	pop	ecx
   846 00000614 7502                    	jnz	short md_info_msg_ok
   847 00000616 E2ED                    	loop	md_info_msg_wait
   848                                  md_info_msg_ok:
   849                                  	; 30/06/2015
   850 00000618 E8942C0000              	call	sys_init
   851                                  	;
   852                                  	;jmp 	cpu_reset ; 22/02/2015
   853                                  hang:
   854                                  	; 24/12/2021
   855 0000061D 29C0                    	sub	eax, eax
   856                                  _hang:	
   857                                  	; 23/02/2015
   858                                  	;sti			; Enable interrupts
   859 0000061F F4                      	hlt
   860                                  	;
   861                                  	;nop
   862                                  	;; 03/12/2014
   863                                  	;; 28/08/2014
   864                                  	;mov	ah, 11h
   865                                  	;call	getc
   866                                  	;jz      _c8
   867                                  	;
   868                                  	; 23/02/2015
   869                                  	; 06/02/2015
   870                                  	; 07/09/2014
   871 00000620 31DB                    	xor	ebx, ebx
   872 00000622 8A1D[266B0000]          	mov	bl, [ptty]	; active_page
   873 00000628 89DE                    	mov	esi, ebx
   874 0000062A 66D1E6                  	shl 	si, 1
   875 0000062D 81C6[286B0000]          	add	esi, ttychr
   876 00000633 668B06                  	mov	ax, [esi]
   877                                  	;and	ax, ax
   878                                  	;;jz	short _c8
   879                                  	;jz	short hang
   880                                  	; 24/12/2021
   881 00000636 21C0                    	and	eax, eax
   882 00000638 74E5                    	jz	short _hang
   883 0000063A 66C7060000              	mov	word [esi], 0
   884 0000063F 80FB03                  	cmp	bl, 3		; Video page 3
   885                                  	;jb	short _c8
   886 00000642 72D9                    	jb	short hang
   887                                  	;	
   888                                  	; 02/09/2014
   889 00000644 B40E                    	mov	ah, 0Eh		; Yellow character 
   890                                  				; on black background
   891                                  	; 24/12/2021 (32 bit reg push-pop)
   892                                  	; 07/09/2014
   893                                  nxtl:
   894 00000646 53                      	push	ebx
   895                                  	;
   896                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   897                                  				; bh = 0 (video mode)
   898                                  				; Retro UNIX 386 v1 - Video Mode 0
   899                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   900 00000647 50                      	push	eax
   901 00000648 E87A0D0000              	call 	write_tty
   902 0000064D 58                      	pop	eax
   903                                  	;pop	bx
   904 0000064E 5B                      	pop	ebx
   905 0000064F 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   906                                  	;jne	short _c8
   907 00000651 75CA                    	jne	short hang
   908 00000653 B00A                    	mov	al, 0Ah		; next line
   909 00000655 EBEF                    	jmp	short nxtl
   910                                  	
   911                                  ;_c8:
   912                                  ;	; 25/08/2014
   913                                  ;	cli			; Disable interrupts
   914                                  ;	mov	al, [scounter + 1]
   915                                  ;	and	al, al
   916                                  ;	jnz	hang
   917                                  ;	call	rtc_p
   918                                  ;	jmp     hang
   919                                  
   920                                  
   921                                  	; 27/08/2014
   922                                  	; 20/08/2014
   923                                  printk:
   924                                          ;mov    edi, [scr_row]
   925                                  pkl:
   926 00000657 AC                      	lodsb
   927 00000658 08C0                    	or 	al, al
   928 0000065A 7404                    	jz	short pkr
   929 0000065C 66AB                    	stosw
   930 0000065E EBF7                    	jmp	short pkl
   931                                  pkr:
   932 00000660 C3                      	retn
   933                                  
   934                                  ; 25/07/2015
   935                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   936                                  ; 17/02/2015
   937                                  ; 06/02/2015 (unix386.s)
   938                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   939                                  ;
   940                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   941                                  ;
   942                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   943                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   944                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   945                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   946                                  ;									       :
   947                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   948                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   949                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   950                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   951                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   952                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   953                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   954                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   955                                  ;-------------------------------------------------------------------------------
   956                                  ;
   957                                  
   958                                  timer_int:	; IRQ 0
   959                                  ;int_08h:	; Timer
   960                                  	; 14/10/2015
   961                                  	; Here, we are simulating system call entry (for task switch)
   962                                  	; (If multitasking is enabled, 
   963                                  	; 'clock' procedure may jump to 'sysrelease')
   964 00000661 1E                      	push	ds
   965 00000662 06                      	push	es
   966 00000663 0FA0                    	push	fs
   967 00000665 0FA8                    	push	gs
   968 00000667 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   969 00000668 66B91000                	mov     cx, KDATA
   970 0000066C 8ED9                            mov     ds, cx
   971 0000066E 8EC1                            mov     es, cx
   972 00000670 8EE1                            mov     fs, cx
   973 00000672 8EE9                            mov     gs, cx
   974                                  	;
   975 00000674 0F20D9                  	mov	ecx, cr3
   976 00000677 890D[1A070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   977                                  	;
   978 0000067D 3B0D[F86A0000]          	cmp 	ecx, [k_page_dir]
   979 00000683 741F                    	je	short T3
   980                                  	;
   981                                  	; timer interrupt has been occurred while OS is in user mode
   982 00000685 A3[B86E0000]            	mov 	[u.r0], eax
   983 0000068A 89E1                    	mov	ecx, esp
   984 0000068C 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   985 0000068F 890D[B06E0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   986 00000695 8925[B46E0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   987                                  	;
   988 0000069B 8B0D[F86A0000]          	mov	ecx, [k_page_dir]
   989 000006A1 0F22D9                  	mov	cr3, ecx
   990                                  T3:
   991 000006A4 FB                      	sti				; INTERRUPTS BACK ON
   992 000006A5 66FF05[746B0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   993 000006AC 7507                    	JNZ	short T4		; GO TO TEST_DAY
   994 000006AE 66FF05[766B0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   995                                  T4:					; TEST_DAY
   996 000006B5 66833D[766B0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   997 000006BD 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   998 000006BF 66813D[746B0000]B0-     	CMP	word [TIMER_LOW],0B0H
   998 000006C7 00                 
   999 000006C8 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1000                                  
  1001                                  ;-----	TIMER HAS GONE 24 HOURS
  1002                                  	;;SUB	AX,AX
  1003                                  	;MOV	[TIMER_HIGH],AX
  1004                                  	;MOV	[TIMER_LOW],AX
  1005 000006CA 29C0                    	sub	eax, eax
  1006 000006CC A3[746B0000]            	mov	[TIMER_LH], eax
  1007                                  	;	
  1008 000006D1 C605[786B0000]01        	MOV	byte [TIMER_OFL],1
  1009                                  
  1010                                  ;-----	TEST FOR DISKETTE TIME OUT
  1011                                  
  1012                                  T5:
  1013                                  	; 23/12/2014
  1014 000006D8 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1015                                  					; (9090h) if a floppy disk
  1016                                  					; is detected.
  1017                                  	;mov	al,[CS:MOTOR_COUNT]
  1018 000006DA A0[7B6B0000]            	mov	al, [MOTOR_COUNT]
  1019 000006DF FEC8                    	dec	al
  1020                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1021 000006E1 A2[7B6B0000]            	mov	[MOTOR_COUNT], al
  1022                                  	;mov	[ORG_MOTOR_COUNT], al
  1023 000006E6 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1024 000006E8 B0F0                    	mov 	al,0F0h
  1025                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1026 000006EA 2005[7A6B0000]          	and	[MOTOR_STATUS], al
  1027                                  	;and	[ORG_MOTOR_STATUS], al
  1028 000006F0 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1029                                  					; bit 2 = enable controller
  1030                                  					;	1 = normal operation
  1031                                  					;	0 = reset	
  1032                                  					; bit 0, 1 = drive select
  1033                                  					; bit 4-7 = motor running bits 
  1034 000006F2 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1035 000006F6 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1036                                  T6:	
  1037                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1038                                  					; TIMER TICK INTERRUPT
  1039                                  	;;inc	word [wait_count] ;;27/02/2015
  1040                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1041                                  	;;;;cli
  1042                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1043 000006F7 FF15[12070000]          	call	[x_timer] ; 14/05/2015
  1044                                  T7:
  1045                                  	; 14/10/2015
  1046 000006FD B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1047 000006FF FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1048 00000700 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1049                                  	;
  1050 00000702 A1[1A070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1051 00000707 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1052                                  	;
  1053 0000070A 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1054                                  	;
  1055 0000070B 0FA9                    	pop	gs
  1056 0000070D 0FA1                    	pop	fs
  1057 0000070F 07                      	pop	es
  1058 00000710 1F                      	pop	ds
  1059 00000711 CF                      	iretd	; return from interrupt
  1060                                  
  1061                                  
  1062                                  ; ////////////////
  1063                                  
  1064                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1065                                  x_timer:
  1066 00000712 [1E070000]              	dd 	u_timer			; 14/05/2015
  1067                                  	;dd	clock
  1068                                  
  1069                                  ; 26/02/2022 - Real time clock (digital) output demo (sys emt)
  1070                                  x_rtci:
  1071 00000716 [540A0000]              	dd	rtc_p	; (temporary demo code)	; 26/02/2022
  1072                                  
  1073                                  ; 14/10/2015
  1074 0000071A 00000000                cr3reg: dd 0
  1075                                  
  1076                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1077                                  	; 06/02/2015
  1078                                  	; 07/09/2014
  1079                                  	; 21/08/2014
  1080                                  u_timer:
  1081                                  ;timer_int:	; IRQ 0
  1082                                  	; 06/02/2015
  1083                                  	;push	eax
  1084                                  	;push	edx
  1085                                  	;push	ecx
  1086                                  	;push	ebx
  1087                                  	;push	ds
  1088                                  	;push	es
  1089                                  	;mov	eax, KDATA
  1090                                  	;mov	ds, ax
  1091                                  	;mov	es, ax
  1092 0000071E FF05[3C6B0000]          	inc	dword [tcount]
  1093 00000724 BB[C2660000]            	mov	ebx, tcountstr + 4
  1094                                  	;mov	ax, [tcount]
  1095                                  	; 24/12/2021
  1096 00000729 A1[3C6B0000]            	mov	eax, [tcount]
  1097 0000072E B90A000000              	mov	ecx, 10
  1098                                  rp_divtcnt:
  1099 00000733 31D2                    	xor	edx, edx
  1100 00000735 F7F1                    	div	ecx
  1101 00000737 80C230                  	add	dl, 30h
  1102 0000073A 8813                    	mov	[ebx], dl
  1103                                  	;or	ax, ax
  1104                                  	; 24/12/2021
  1105 0000073C 09C0                    	or	eax, eax
  1106 0000073E 7403                    	jz	short print_lzero
  1107 00000740 4B                      	dec	ebx
  1108 00000741 EBF0                    	jmp	short rp_divtcnt
  1109                                  print_lzero:
  1110 00000743 81FB[BE660000]          	cmp	ebx, tcountstr
  1111 00000749 7606                    	jna	short print_tcount
  1112 0000074B 4B                      	dec	ebx
  1113 0000074C C60330                   	mov	byte [ebx], 30h
  1114 0000074F EBF2                    	jmp	short print_lzero
  1115                                  print_tcount:
  1116 00000751 56                      	push	esi
  1117 00000752 57                      	push	edi
  1118 00000753 BE[9A660000]            	mov	esi, timer_msg ; Timer interrupt message
  1119                                  	; 07/09/2014
  1120                                  	;mov	bx, 1	; Video page 1
  1121                                  	; 24/12/2021
  1122 00000758 29DB                    	sub	ebx, ebx
  1123                                  	;inc	bl ; ebx = 1
  1124                                  	; 02/01/2022
  1125 0000075A B306                    	mov	bl, 6	; Video page 6
  1126                                  ptmsg:
  1127 0000075C AC                      	lodsb
  1128 0000075D 08C0                    	or	al, al
  1129 0000075F 740D                    	jz	short ptmsg_ok
  1130 00000761 56                      	push	esi
  1131                                  	;push	bx
  1132                                  	; 24/12/2021
  1133 00000762 53                              push	ebx
  1134 00000763 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1135 00000765 E85D0C0000              	call 	write_tty
  1136                                  	;pop	bx
  1137                                  	; 24/12/2021
  1138 0000076A 5B                      	pop	ebx
  1139 0000076B 5E                      	pop	esi
  1140 0000076C EBEE                    	jmp	short ptmsg
  1141                                  	;; 27/08/2014
  1142                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1143                                  	;call	printk
  1144                                  	;
  1145                                  ptmsg_ok:
  1146                                  	; 07/09/2014
  1147                                  	;xor	dx, dx		; column 0, row 0
  1148                                  	; 24/12/2021
  1149 0000076E 31D2                    	xor	edx, edx
  1150 00000770 E85C0D0000              	call	set_cpos	; set cursor position to 0,0 
  1151                                  	; 23/02/2015
  1152                                  	; 25/08/2014
  1153                                  	;mov	ebx, scounter		; (seconds counter)
  1154                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1155                                  ;	dec	byte [scounter+1]
  1156                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1157                                  ;	jns	short u_timer_retn
  1158                                  	; 26/02/2015
  1159                                  ;	call	rtc_p
  1160                                  ;	mov	ebx, scounter		; (seconds counter)
  1161                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1162                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1163                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1164                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1165                                  ;	mov	byte [ebx], 5
  1166                                  ;	inc	byte [ebx+1] ; 19
  1167                                  ;;timer_eoi:
  1168                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1169                                  ;;	out	20h, al	; 8259 PORT
  1170                                  	;
  1171                                  ;u_timer_retn:  ; 06/02/2015
  1172 00000775 5F                      	pop	edi
  1173 00000776 5E                      	pop	esi
  1174                                  	;pop	es
  1175                                  	;pop	ds
  1176                                  	;pop	ebx
  1177                                  	;pop	ecx
  1178                                  	;pop	edx
  1179                                  	;pop	eax
  1180                                  	;iret
  1181 00000777 C3                      	retn	; 06/02/2015
  1182                                  
  1183                                  	; 28/08/2014
  1184                                  irq0:
  1185 00000778 6A00                            push 	dword 0
  1186 0000077A EB48                    	jmp	short which_irq
  1187                                  irq1:
  1188 0000077C 6A01                            push 	dword 1
  1189 0000077E EB44                    	jmp	short which_irq
  1190                                  irq2:
  1191 00000780 6A02                            push 	dword 2
  1192 00000782 EB40                    	jmp	short which_irq
  1193                                  irq3:
  1194                                  	; 20/11/2015
  1195                                  	; 24/10/2015
  1196 00000784 2EFF15[D7390000]        	call	dword [cs:com2_irq3]
  1197 0000078B 6A03                    	push 	dword 3
  1198 0000078D EB35                    	jmp	short which_irq
  1199                                  irq4:
  1200                                  	; 20/11/2015
  1201                                  	; 24/10/2015
  1202 0000078F 2EFF15[D3390000]        	call	dword [cs:com1_irq4]
  1203 00000796 6A04                            push 	dword 4
  1204 00000798 EB2A                    	jmp	short which_irq
  1205                                  irq5:
  1206 0000079A 6A05                            push 	dword 5
  1207 0000079C EB26                    	jmp	short which_irq
  1208                                  irq6:
  1209 0000079E 6A06                            push 	dword 6
  1210 000007A0 EB22                    	jmp	short which_irq
  1211                                  irq7:
  1212 000007A2 6A07                            push 	dword 7
  1213 000007A4 EB1E                    	jmp	short which_irq
  1214                                  irq8:
  1215 000007A6 6A08                            push 	dword 8
  1216 000007A8 EB1A                    	jmp	short which_irq
  1217                                  irq9:
  1218 000007AA 6A09                            push 	dword 9
  1219 000007AC EB16                    	jmp	short which_irq
  1220                                  irq10:
  1221 000007AE 6A0A                            push 	dword 10
  1222 000007B0 EB12                    	jmp	short which_irq
  1223                                  irq11:
  1224 000007B2 6A0B                            push 	dword 11
  1225 000007B4 EB0E                    	jmp	short which_irq
  1226                                  irq12:
  1227 000007B6 6A0C                            push 	dword 12
  1228 000007B8 EB0A                    	jmp	short which_irq
  1229                                  irq13:
  1230 000007BA 6A0D                            push 	dword 13
  1231 000007BC EB06                    	jmp	short which_irq
  1232                                  irq14:
  1233 000007BE 6A0E                            push 	dword 14
  1234 000007C0 EB02                    	jmp	short which_irq
  1235                                  irq15:
  1236 000007C2 6A0F                            push 	dword 15
  1237                                  	;jmp	short which_irq
  1238                                  
  1239                                  	; 19/10/2015
  1240                                  	; 29/08/2014
  1241                                  	; 21/08/2014
  1242                                  which_irq:
  1243 000007C4 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1244 000007C7 53                      	push	ebx
  1245 000007C8 56                      	push	esi
  1246 000007C9 57                      	push	edi
  1247 000007CA 1E                      	push 	ds
  1248 000007CB 06                      	push 	es
  1249                                  	;
  1250 000007CC 88C3                    	mov	bl, al
  1251                                  	;
  1252 000007CE B810000000              	mov	eax, KDATA
  1253 000007D3 8ED8                    	mov	ds, ax
  1254 000007D5 8EC0                    	mov	es, ax
  1255                                  	; 19/10/2015
  1256 000007D7 FC                      	cld
  1257                                          ; 27/08/2014
  1258 000007D8 8105[48660000]A000-             add     dword [scr_row], 0A0h
  1258 000007E0 0000               
  1259                                  	;
  1260 000007E2 B417                    	mov	ah, 17h	; blue (1) background, 
  1261                                  			; light gray (7) forecolor
  1262 000007E4 8B3D[48660000]                  mov     edi, [scr_row]
  1263 000007EA B049                    	mov	al, 'I'
  1264 000007EC 66AB                    	stosw
  1265 000007EE B052                    	mov	al, 'R'
  1266 000007F0 66AB                    	stosw
  1267 000007F2 B051                    	mov	al, 'Q'
  1268 000007F4 66AB                    	stosw
  1269 000007F6 B020                    	mov	al, ' '
  1270 000007F8 66AB                    	stosw
  1271 000007FA 88D8                    	mov	al, bl
  1272 000007FC 3C0A                    	cmp	al, 10
  1273 000007FE 7208                    	jb	short iix
  1274 00000800 B031                    	mov	al, '1'
  1275 00000802 66AB                    	stosw
  1276 00000804 88D8                    	mov	al, bl
  1277 00000806 2C0A                    	sub	al, 10
  1278                                  iix:
  1279 00000808 0430                    	add	al, '0'
  1280 0000080A 66AB                    	stosw
  1281 0000080C B020                    	mov	al, ' '
  1282 0000080E 66AB                    	stosw
  1283 00000810 B021                    	mov	al, '!'
  1284 00000812 66AB                    	stosw
  1285 00000814 B020                    	mov	al, ' '
  1286 00000816 66AB                    	stosw
  1287                                  	; 23/02/2015
  1288 00000818 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1289                                  	;jna	iiret
  1290                                  	; 02/01/2022
  1291 0000081B 7604                    	jna	short iiz
  1292                                  iiy:
  1293 0000081D B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1294 0000081F E6A0                    	out	0A0h, al ; the 2nd 8259
  1295                                  iiz:
  1296 00000821 E983010000              	jmp     iiret
  1297                                  	;
  1298                                  	; 22/08/2014
  1299                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1300                                  	;out	20h, al	; 8259 PORT
  1301                                  	;
  1302                                  	;pop	es
  1303                                  	;pop	ds
  1304                                  	;pop	edi
  1305                                  	;pop	esi
  1306                                  	;pop	ebx
  1307                                  	;pop 	eax
  1308                                  	;iret
  1309                                  
  1310                                  	; 02/04/2015
  1311                                  	; 25/08/2014
  1312                                  exc0:
  1313 00000826 6A00                            push 	dword 0
  1314 00000828 E990000000                      jmp     cpu_except
  1315                                  exc1:
  1316 0000082D 6A01                            push 	dword 1
  1317 0000082F E989000000                      jmp     cpu_except
  1318                                  exc2:
  1319 00000834 6A02                            push 	dword 2
  1320 00000836 E982000000                      jmp     cpu_except
  1321                                  exc3:
  1322 0000083B 6A03                            push 	dword 3
  1323 0000083D EB7E                            jmp     cpu_except
  1324                                  exc4:
  1325 0000083F 6A04                            push 	dword 4
  1326 00000841 EB7A                            jmp     cpu_except
  1327                                  exc5:
  1328 00000843 6A05                            push 	dword 5
  1329 00000845 EB76                            jmp     cpu_except
  1330                                  exc6:
  1331 00000847 6A06                            push 	dword 6
  1332 00000849 EB72                            jmp     cpu_except
  1333                                  exc7:
  1334 0000084B 6A07                            push 	dword 7
  1335 0000084D EB6E                            jmp     cpu_except
  1336                                  exc8:
  1337                                  	; [esp] = Error code
  1338 0000084F 6A08                            push 	dword 8
  1339 00000851 EB5C                            jmp     cpu_except_en
  1340                                  exc9:
  1341 00000853 6A09                            push 	dword 9
  1342 00000855 EB66                            jmp     cpu_except
  1343                                  exc10:
  1344                                  	; [esp] = Error code
  1345 00000857 6A0A                            push 	dword 10
  1346 00000859 EB54                            jmp     cpu_except_en
  1347                                  exc11:
  1348                                  	; [esp] = Error code
  1349 0000085B 6A0B                            push 	dword 11
  1350 0000085D EB50                            jmp     cpu_except_en
  1351                                  exc12:
  1352                                  	; [esp] = Error code
  1353 0000085F 6A0C                            push 	dword 12
  1354 00000861 EB4C                            jmp     cpu_except_en
  1355                                  exc13:
  1356                                  	; [esp] = Error code
  1357 00000863 6A0D                            push 	dword 13
  1358 00000865 EB48                            jmp     cpu_except_en
  1359                                  exc14:
  1360                                  	; [esp] = Error code
  1361 00000867 6A0E                            push 	dword 14
  1362 00000869 EB44                    	jmp	short cpu_except_en
  1363                                  exc15:
  1364 0000086B 6A0F                            push 	dword 15
  1365 0000086D EB4E                            jmp     cpu_except
  1366                                  exc16:
  1367 0000086F 6A10                            push 	dword 16
  1368 00000871 EB4A                            jmp     cpu_except
  1369                                  exc17:
  1370                                  	; [esp] = Error code
  1371 00000873 6A11                            push 	dword 17
  1372 00000875 EB38                    	jmp	short cpu_except_en
  1373                                  exc18:
  1374 00000877 6A12                            push 	dword 18
  1375 00000879 EB42                    	jmp	short cpu_except
  1376                                  exc19:
  1377 0000087B 6A13                            push 	dword 19
  1378 0000087D EB3E                    	jmp	short cpu_except
  1379                                  exc20:
  1380 0000087F 6A14                            push 	dword 20
  1381 00000881 EB3A                    	jmp	short cpu_except
  1382                                  exc21:
  1383 00000883 6A15                            push 	dword 21
  1384 00000885 EB36                    	jmp	short cpu_except
  1385                                  exc22:
  1386 00000887 6A16                            push 	dword 22
  1387 00000889 EB32                    	jmp	short cpu_except
  1388                                  exc23:
  1389 0000088B 6A17                            push 	dword 23
  1390 0000088D EB2E                    	jmp	short cpu_except
  1391                                  exc24:
  1392 0000088F 6A18                            push 	dword 24
  1393 00000891 EB2A                    	jmp	short cpu_except
  1394                                  exc25:
  1395 00000893 6A19                            push 	dword 25
  1396 00000895 EB26                    	jmp	short cpu_except
  1397                                  exc26:
  1398 00000897 6A1A                            push 	dword 26
  1399 00000899 EB22                    	jmp	short cpu_except
  1400                                  exc27:
  1401 0000089B 6A1B                            push 	dword 27
  1402 0000089D EB1E                    	jmp	short cpu_except
  1403                                  exc28:
  1404 0000089F 6A1C                            push 	dword 28
  1405 000008A1 EB1A                    	jmp	short cpu_except
  1406                                  exc29:
  1407 000008A3 6A1D                            push 	dword 29
  1408 000008A5 EB16                    	jmp	short cpu_except
  1409                                  exc30:
  1410 000008A7 6A1E                            push 	dword 30
  1411 000008A9 EB04                    	jmp	short cpu_except_en
  1412                                  exc31:
  1413 000008AB 6A1F                            push 	dword 31
  1414 000008AD EB0E                            jmp     short cpu_except
  1415                                  
  1416                                  	; 02/01/2022
  1417                                  	; 19/10/2015
  1418                                  	; 19/09/2015
  1419                                  	; 01/09/2015
  1420                                  	; 28/08/2015
  1421                                  	; 28/08/2014
  1422                                  cpu_except_en:
  1423 000008AF 87442404                	xchg	eax, [esp+4] ; Error code
  1424 000008B3 36A3[A86B0000]          	mov	[ss:error_code], eax
  1425 000008B9 58                      	pop	eax  ; Exception number
  1426 000008BA 870424                  	xchg	eax, [esp]
  1427                                  		; eax = eax before exception
  1428                                  		; [esp] -> exception number
  1429                                  		; [esp+4] -> EIP to return
  1430                                  	; 19/10/2015
  1431                                  	; 19/09/2015
  1432                                  	; 01/09/2015
  1433                                  	; 28/08/2015
  1434                                  	; 29/08/2014
  1435                                  	; 28/08/2014
  1436                                  	; 25/08/2014
  1437                                  	; 21/08/2014
  1438                                  cpu_except:	; CPU Exceptions
  1439 000008BD FC                      	cld
  1440 000008BE 870424                  	xchg	eax, [esp] 
  1441                                  		; eax = Exception number
  1442                                  		; [esp] = eax (before exception)
  1443 000008C1 53                      	push	ebx
  1444 000008C2 56                      	push	esi
  1445 000008C3 57                      	push	edi
  1446 000008C4 1E                      	push 	ds
  1447 000008C5 06                      	push 	es
  1448                                  	; 28/08/2015
  1449 000008C6 66BB1000                	mov	bx, KDATA
  1450 000008CA 8EDB                    	mov	ds, bx
  1451 000008CC 8EC3                    	mov	es, bx
  1452 000008CE 0F20DB                  	mov	ebx, cr3
  1453 000008D1 53                      	push	ebx ; (*) page directory
  1454                                  	; 19/10/2015
  1455 000008D2 FC                      	cld
  1456                                  	; 25/03/2015
  1457 000008D3 8B1D[F86A0000]          	mov	ebx, [k_page_dir]
  1458 000008D9 0F22DB                  	mov	cr3, ebx
  1459                                  	; 28/08/2015
  1460 000008DC 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1461 000008DF 7513                    	jne	short cpu_except_nfp
  1462 000008E1 E885270000              	call	page_fault_handler
  1463 000008E6 21C0                    	and 	eax, eax
  1464                                  	;jz	iiretp ; 01/09/2015
  1465                                  	; 02/01/2022
  1466 000008E8 7505                    	jnz	short cpu_except_pf
  1467 000008EA E9B6000000              	jmp	iiretp
  1468                                  cpu_except_pf:
  1469 000008EF B80E000000              	mov	eax, 0Eh ; 14
  1470                                  cpu_except_nfp:
  1471                                  	; 02/04/2015
  1472 000008F4 BB[1D060000]            	mov	ebx, hang
  1473 000008F9 875C241C                	xchg	ebx, [esp+28]
  1474                                  		; EIP (points to instruction which faults)
  1475                                  	  	; New EIP (hang)
  1476 000008FD 891D[AC6B0000]          	mov	[FaultOffset], ebx
  1477 00000903 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1478 0000090B 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1479                                  	;
  1480 00000913 88C4                    	mov	ah, al
  1481 00000915 240F                    	and	al, 0Fh
  1482 00000917 3C09                    	cmp	al, 9
  1483 00000919 7602                    	jna	short h1ok
  1484 0000091B 0407                    	add	al, 'A'-':'
  1485                                  h1ok:
  1486 0000091D D0EC                    	shr	ah, 1
  1487 0000091F D0EC                    	shr	ah, 1
  1488 00000921 D0EC                    	shr	ah, 1
  1489 00000923 D0EC                    	shr	ah, 1
  1490 00000925 80FC09                  	cmp	ah, 9
  1491 00000928 7603                    	jna	short h2ok
  1492 0000092A 80C407                  	add	ah, 'A'-':'
  1493                                  h2ok:	
  1494 0000092D 86E0                    	xchg 	ah, al	
  1495 0000092F 66053030                	add	ax, '00'
  1496 00000933 66A3[D6660000]          	mov	[excnstr], ax
  1497                                  	;
  1498                                  	; 29/08/2014
  1499 00000939 A1[AC6B0000]            	mov	eax, [FaultOffset]
  1500 0000093E 51                      	push	ecx
  1501 0000093F 52                      	push	edx
  1502 00000940 89E3                    	mov	ebx, esp
  1503                                  	; 28/08/2015
  1504 00000942 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1505                                  			  ; to hexadecimal string
  1506                                  	;mov	ecx, 10	    ; divisor to convert
  1507                                  			    ; binary number to decimal string
  1508                                  b2d1:
  1509 00000947 31D2                    	xor	edx, edx
  1510 00000949 F7F1                    	div	ecx
  1511                                  	;push	dx
  1512                                  	; 02/01/2022
  1513 0000094B 52                      	push	edx
  1514 0000094C 39C8                    	cmp	eax, ecx
  1515 0000094E 73F7                    	jnb	short b2d1
  1516 00000950 BF[E1660000]            	mov	edi, EIPstr ; EIP value
  1517                                  			    ; points to instruction which faults
  1518                                  	; 28/08/2015
  1519 00000955 89C2                    	mov	edx, eax
  1520                                  b2d2:
  1521                                  	;add	al, '0'
  1522 00000957 8A82[07170000]          	mov	al, [edx+hexchrs]
  1523 0000095D AA                      	stosb		    ; write hexadecimal digit to its place
  1524 0000095E 39E3                    	cmp	ebx, esp
  1525 00000960 7605                    	jna	short b2d3
  1526                                  	; 02/01/2022
  1527 00000962 58                      	pop	eax
  1528                                  	;pop	ax
  1529 00000963 88C2                    	mov	dl, al
  1530 00000965 EBF0                    	jmp	short b2d2
  1531                                  b2d3:
  1532 00000967 B068                    	mov 	al, 'h' ; 28/08/2015
  1533 00000969 AA                      	stosb
  1534 0000096A B020                    	mov	al, 20h	    ; space
  1535 0000096C AA                      	stosb
  1536 0000096D 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1537 0000096F AA                      	stosb
  1538                                  	;
  1539 00000970 5A                      	pop	edx
  1540 00000971 59                      	pop	ecx
  1541                                  	;
  1542 00000972 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1543                                  			; white (F) forecolor
  1544 00000974 BE[C6660000]            	mov	esi, exc_msg ; message offset
  1545                                  	;
  1546 00000979 EB11                    	jmp	short piemsg
  1547                                  	;
  1548                                          ;add    dword [scr_row], 0A0h
  1549                                          ;mov    edi, [scr_row]
  1550                                          ;
  1551                                  	;call 	printk
  1552                                  	;
  1553                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1554                                  	;out	20h, al	; 8259 PORT
  1555                                  	;
  1556                                  	;pop	es
  1557                                  	;pop	ds
  1558                                  	;pop	edi
  1559                                  	;pop	esi
  1560                                  	;pop 	eax
  1561                                  	;iret
  1562                                  	
  1563                                  	; 28/08/2015
  1564                                  	; 23/02/2015
  1565                                  	; 20/08/2014
  1566                                  ignore_int:
  1567 0000097B 50                      	push	eax
  1568 0000097C 53                      	push	ebx ; 23/02/2015
  1569 0000097D 56                      	push	esi
  1570 0000097E 57                      	push	edi
  1571 0000097F 1E                      	push 	ds
  1572 00000980 06                      	push 	es
  1573                                  	; 28/08/2015
  1574 00000981 0F20D8                  	mov	eax, cr3
  1575 00000984 50                      	push	eax ; (*) page directory
  1576                                  	;
  1577 00000985 B467                    	mov	ah, 67h	; brown (6) background, 
  1578                                  			; light gray (7) forecolor
  1579 00000987 BE[84660000]            	mov	esi, int_msg ; message offset
  1580                                  piemsg:
  1581                                          ; 27/08/2014
  1582 0000098C 8105[48660000]A000-             add     dword [scr_row], 0A0h
  1582 00000994 0000               
  1583 00000996 8B3D[48660000]                  mov     edi, [scr_row]
  1584                                          ;
  1585 0000099C E8B6FCFFFF              	call 	printk
  1586                                  	;
  1587                                  	; 23/02/2015
  1588 000009A1 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1589 000009A3 E6A0                    	out	0A0h, al ; the 2nd 8259
  1590                                  iiretp: ; 01/09/2015
  1591                                  	; 28/08/2015
  1592 000009A5 58                      	pop	eax ; (*) page directory
  1593 000009A6 0F22D8                  	mov	cr3, eax
  1594                                  	;
  1595                                  iiret:
  1596                                  	; 22/08/2014
  1597 000009A9 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1598 000009AB E620                    	out	20h, al	; 8259 PORT
  1599                                  	;
  1600 000009AD 07                      	pop	es
  1601 000009AE 1F                      	pop	ds
  1602 000009AF 5F                      	pop	edi
  1603 000009B0 5E                      	pop	esi
  1604 000009B1 5B                      	pop	ebx ; 29/08/2014
  1605 000009B2 58                      	pop 	eax
  1606 000009B3 CF                      	iretd
  1607                                  
  1608                                  	; 26/02/2022
  1609                                  	; 26/02/2015
  1610                                  	; 07/09/2014
  1611                                  	; 25/08/2014
  1612                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1613                                  	; 22/08/2014
  1614 000009B4 50                      	push	eax
  1615 000009B5 53                      	push	ebx ; 29/08/2014
  1616 000009B6 56                      	push	esi
  1617 000009B7 57                      	push	edi
  1618 000009B8 1E                      	push 	ds
  1619 000009B9 06                      	push 	es
  1620                                  	;
  1621 000009BA B810000000              	mov	eax, KDATA
  1622 000009BF 8ED8                    	mov	ds, ax
  1623 000009C1 8EC0                    	mov	es, ax
  1624                                  	;
  1625                                  	; 25/08/2014
  1626                                  	;call	rtc_p
  1627                                  	; 26/02/2022
  1628 000009C3 FF15[16070000]          	call	[x_rtci]
  1629                                  	;
  1630                                  	; 22/02/2015 - dsectpm.s
  1631                                  	; [ source: http://wiki.osdev.org/RTC ]
  1632                                  	; read status register C to complete procedure
  1633                                  	;(it is needed to get a next IRQ 8) 
  1634 000009C9 B00C                    	mov	al, 0Ch ; 
  1635 000009CB E670                    	out	70h, al ; select register C
  1636 000009CD 90                      	nop
  1637 000009CE E471                    	in	al, 71h ; just throw away contents
  1638                                  	; 22/02/2015
  1639 000009D0 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1640 000009D2 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1641                                  	;
  1642 000009D4 EBD3                    	jmp	short iiret	
  1643                                  
  1644                                  	; 22/08/2014
  1645                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1646                                  	; (INT 1Ah)
  1647                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1648                                  time_of_day:
  1649 000009D6 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1650 000009DB 726F                            jc      short rtc_retn 
  1651 000009DD B000                    	mov	al, CMOS_SECONDS
  1652 000009DF E847010000              	call	CMOS_READ
  1653 000009E4 A2[6C6B0000]            	mov	[time_seconds], al 
  1654 000009E9 B002                    	mov	al, CMOS_MINUTES
  1655 000009EB E83B010000              	call	CMOS_READ
  1656 000009F0 A2[6D6B0000]            	mov	[time_minutes], al 
  1657 000009F5 B004                    	mov	al, CMOS_HOURS
  1658 000009F7 E82F010000              	call	CMOS_READ
  1659 000009FC A2[6E6B0000]                    mov     [time_hours], al
  1660 00000A01 B006                    	mov	al, CMOS_DAY_WEEK 
  1661 00000A03 E823010000              	call	CMOS_READ
  1662 00000A08 A2[6F6B0000]            	mov	[date_wday], al
  1663 00000A0D B007                     	mov	al, CMOS_DAY_MONTH
  1664 00000A0F E817010000              	call	CMOS_READ
  1665 00000A14 A2[706B0000]            	mov	[date_day], al
  1666 00000A19 B008                    	mov	al, CMOS_MONTH
  1667 00000A1B E80B010000              	call	CMOS_READ
  1668 00000A20 A2[716B0000]            	mov	[date_month], al
  1669 00000A25 B009                    	mov	al, CMOS_YEAR
  1670 00000A27 E8FF000000              	call	CMOS_READ
  1671 00000A2C A2[726B0000]            	mov	[date_year], al
  1672 00000A31 B032                    	mov	al, CMOS_CENTURY
  1673 00000A33 E8F3000000              	call	CMOS_READ
  1674 00000A38 A2[736B0000]            	mov	[date_century], al
  1675                                  	;
  1676 00000A3D B000                    	mov	al, CMOS_SECONDS
  1677 00000A3F E8E7000000              	call 	CMOS_READ
  1678 00000A44 3A05[6C6B0000]          	cmp	al, [time_seconds]
  1679 00000A4A 758A                    	jne	short time_of_day
  1680                                  
  1681                                  rtc_retn:
  1682 00000A4C C3                      	retn
  1683                                  
  1684                                  rtci_default:
  1685                                  	; 26/02/2022 (Temporary!)
  1686                                  	; (default real time clock handler in multitasking mode)
  1687                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1688 00000A4D FF05[B46B0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1689                                  			; (not used in anywhere of kernel for now!)
  1690 00000A53 C3                      	retn
  1691                                  
  1692                                  rtc_p:	
  1693                                  	; 07/09/2014
  1694                                  	; 29/08/2014
  1695                                  	; 27/08/2014
  1696                                  	; 25/08/2014
  1697                                   	; Print Real Time Clock content
  1698                                  	;
  1699                                  	;
  1700 00000A54 E87DFFFFFF              	call	time_of_day
  1701 00000A59 72F1                    	jc	short rtc_retn
  1702                                  	;
  1703 00000A5B 3A05[38670000]          	cmp	al, [ptime_seconds]
  1704 00000A61 74E9                            je      short rtc_retn ; 29/08/2014
  1705                                  	;
  1706 00000A63 A2[38670000]            	mov	[ptime_seconds], al
  1707                                  	;
  1708 00000A68 A0[736B0000]            	mov	al, [date_century]
  1709 00000A6D E8EA000000              	call	bcd_to_ascii
  1710 00000A72 66A3[05670000]          	mov	[datestr+6], ax
  1711 00000A78 A0[726B0000]            	mov	al, [date_year]
  1712 00000A7D E8DA000000              	call	bcd_to_ascii
  1713 00000A82 66A3[07670000]          	mov	[datestr+8], ax
  1714 00000A88 A0[716B0000]            	mov	al, [date_month]
  1715 00000A8D E8CA000000              	call	bcd_to_ascii
  1716 00000A92 66A3[02670000]          	mov	[datestr+3], ax
  1717 00000A98 A0[706B0000]            	mov	al, [date_day]
  1718 00000A9D E8BA000000              	call	bcd_to_ascii
  1719 00000AA2 66A3[FF660000]          	mov	[datestr], ax
  1720                                  	;
  1721 00000AA8 0FB61D[6F6B0000]        	movzx	ebx, byte [date_wday]
  1722 00000AAF C0E302                  	shl 	bl, 2
  1723 00000AB2 81C3[18670000]          	add	ebx, daytmp
  1724 00000AB8 8B03                    	mov	eax, [ebx]
  1725 00000ABA A3[0A670000]            	mov	[daystr], eax
  1726                                  	;
  1727 00000ABF A0[6E6B0000]            	mov	al, [time_hours]
  1728 00000AC4 E893000000              	call	bcd_to_ascii
  1729 00000AC9 66A3[0E670000]          	mov	[timestr], ax
  1730 00000ACF A0[6D6B0000]            	mov	al, [time_minutes]
  1731 00000AD4 E883000000              	call	bcd_to_ascii
  1732 00000AD9 66A3[11670000]          	mov	[timestr+3], ax
  1733 00000ADF A0[6C6B0000]            	mov	al, [time_seconds]
  1734 00000AE4 E873000000              	call	bcd_to_ascii
  1735 00000AE9 66A3[14670000]          	mov	[timestr+6], ax
  1736                                  	;		
  1737 00000AEF BE[ED660000]            	mov	esi, rtc_msg ; message offset
  1738                                  	; 23/02/2015
  1739 00000AF4 52                      	push	edx
  1740 00000AF5 51                      	push	ecx
  1741                                  	; 07/09/2014
  1742                                  	;mov	bx, 2	; Video page 2
  1743                                  	; 02/01/2022
  1744 00000AF6 29DB                    	sub	ebx, ebx
  1745 00000AF8 B307                    	mov	bl, 7	; Video page 7 
  1746                                  prtmsg:
  1747 00000AFA AC                      	lodsb
  1748 00000AFB 08C0                    	or	al, al
  1749 00000AFD 740D                    	jz	short prtmsg_ok
  1750 00000AFF 56                      	push	esi
  1751                                  	; 02/01/2022
  1752 00000B00 53                      	push	ebx
  1753                                  	;push	bx
  1754 00000B01 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1755                                  			; white (F) forecolor
  1756 00000B03 E8BF080000              	call 	write_tty
  1757                                  	;pop	bx
  1758                                  	; 02/01/2022
  1759 00000B08 5B                      	pop	ebx
  1760 00000B09 5E                      	pop	esi
  1761 00000B0A EBEE                    	jmp	short prtmsg
  1762                                  	;
  1763                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1764                                  	;call	printk
  1765                                  prtmsg_ok:
  1766                                  	; 07/09/2014
  1767                                  	;xor	dx, dx		; column 0, row 0
  1768                                  	; 02/01/2022
  1769 00000B0C 31D2                    	xor	edx, edx
  1770 00000B0E E8BE090000              	call	set_cpos	; set curspor position to 0,0 
  1771                                  	; 23/02/2015
  1772 00000B13 59                      	pop	ecx
  1773 00000B14 5A                      	pop	edx
  1774 00000B15 C3                      	retn
  1775                                  
  1776                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1777                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1778                                  default_irq7:
  1779                                  	; 24/12/2021
  1780                                  	;push	ax
  1781 00000B16 50                      	push	eax
  1782 00000B17 B00B                    	mov	al, 0Bh  ; In-Service register
  1783 00000B19 E620                    	out	20h, al
  1784 00000B1B EB00                            jmp short $+2
  1785 00000B1D EB00                    	jmp short $+2
  1786 00000B1F E420                    	in	al, 20h
  1787 00000B21 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1788 00000B23 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1789 00000B25 B020                            mov     al, 20h ; EOI
  1790 00000B27 E620                    	out	20h, al 
  1791                                  irq7_iret:
  1792                                  	;pop	ax
  1793                                  	; 24/12/2021
  1794 00000B29 58                      	pop	eax
  1795 00000B2A CF                      	iretd	
  1796                                  	
  1797                                  	; 24/12/2021
  1798                                  	; 22/08/2014
  1799                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1800                                  CMOS_READ:
  1801 00000B2B 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1802 00000B2C D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1803 00000B2E F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1804 00000B2F D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1805 00000B31 FA                      	cli		; DISABLE INTERRUPTS
  1806 00000B32 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1807 00000B34 90                      	nop		; I/O DELAY
  1808 00000B35 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1809                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1810                                  	; 24/12/2021
  1811 00000B37 50                      	push	eax
  1812                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1813                                  		     ; ----- 10/06/85 (test4.asm)
  1814 00000B38 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1815                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1816 00000B3A D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1817 00000B3C E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1818                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1819                                  	; 24/12/2021
  1820 00000B3E 58                      	pop	eax
  1821 00000B3F 9D                      	popf	
  1822 00000B40 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1823                                  
  1824                                  	; 22/08/2014
  1825                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1826                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1827 00000B41 51                      	push	ecx
  1828 00000B42 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1829                                  		; mov cx, 800	
  1830                                  UPD_10:
  1831 00000B47 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1832 00000B49 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1833 00000B4A E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1834 00000B4F A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1835 00000B51 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1836 00000B53 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1837 00000B54 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1838 00000B56 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1839                                  		; xor ax, ax
  1840 00000B58 F9                      	stc				; SET CARRY FOR ERROR
  1841                                  UPD_90:
  1842 00000B59 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1843 00000B5A FA                      	cli				; INTERRUPTS OFF DURING SET
  1844 00000B5B C3                      	retn				; RETURN WITH CY FLAG SET
  1845                                  
  1846                                  bcd_to_ascii:
  1847                                  	; 25/08/2014
  1848                                  	; INPUT ->
  1849                                  	;	al = Packed BCD number
  1850                                  	; OUTPUT ->
  1851                                  	;	ax  = ASCII word/number
  1852                                  	;
  1853                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1854                                  	;
  1855 00000B5C D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1856                                  					; AH = AL / 10h
  1857                                  					; AL = AL MOD 10h
  1858 00000B5E 660D3030                	or ax,'00'                      ; Make it ASCII based
  1859                                  
  1860 00000B62 86E0                            xchg ah, al 
  1861                                  	
  1862 00000B64 C3                      	retn	
  1863                                  	
  1864                                  
  1865                                  %include 'keyboard.inc' ; 07/03/2015
  1866                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1867                              <1> ; Last Modification: 23/02/2022
  1868                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1869                              <1> ;
  1870                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1871                              <1> 
  1872                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1873                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1874                              <1> ; 30/06/2015
  1875                              <1> ; 11/03/2015
  1876                              <1> ; 28/02/2015
  1877                              <1> ; 25/02/2015
  1878                              <1> ; 20/02/2015
  1879                              <1> ; 18/02/2015
  1880                              <1> ; 03/12/2014
  1881                              <1> ; 07/09/2014
  1882                              <1> ; KEYBOARD INTERRUPT HANDLER
  1883                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1884                              <1> 
  1885                              <1> ;getch:
  1886                              <1> ;	; 18/02/2015
  1887                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1888                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1889                              <1> ;	; routine, later... (multi tasking ability)
  1890                              <1> ;	; 28/02/2015
  1891                              <1> ;	sti	; enable interrupts
  1892                              <1> ;	;
  1893                              <1> ;	;push	esi
  1894                              <1> ;	;push	ebx
  1895                              <1> ;	;xor	ebx, ebx
  1896                              <1> ;	;mov	bl, [ptty]  ; active_page
  1897                              <1> ;	;mov	esi, ebx
  1898                              <1> ;	;shl 	si, 1
  1899                              <1> ;	;add	esi, ttychr
  1900                              <1> ;getch_1:
  1901                              <1> ;	;mov	ax, [esi]
  1902                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1903                              <1> ;	and	ax, ax
  1904                              <1> ;	jz	short getch_2
  1905                              <1> ;	mov	word [ttychr], 0
  1906                              <1> ;	;mov	word [esi], 0
  1907                              <1> ;	;pop	ebx
  1908                              <1> ;	;pop	esi
  1909                              <1> ;	retn
  1910                              <1> ;getch_2:
  1911                              <1> ;	hlt	; not proper for multi tasking!
  1912                              <1> ;		; (temporary halt for now)
  1913                              <1> ;		; 'sleep' on tty 
  1914                              <1> ;		; will (must) be located here		
  1915                              <1> ;	nop
  1916                              <1> ;	jmp	short getch_1
  1917                              <1> 
  1918                              <1> keyb_int:
  1919                              <1> 	; 23/02/2022
  1920                              <1> 	; 30/06/2015
  1921                              <1> 	; 25/02/2015
  1922                              <1> 	; 20/02/2015
  1923                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1924                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1925                              <1> 	; 30/06/2014
  1926                              <1> 	; 10/05/2013	
  1927                              <1>       	; Retro Unix 8086 v1 feature only!
  1928                              <1> 	; 03/03/2014
  1929                              <1> 	
  1930 00000B65 1E                  <1> 	push	ds
  1931 00000B66 53                  <1> 	push	ebx
  1932 00000B67 50                  <1> 	push	eax
  1933                              <1> 	;
  1934                              <1> 	; 23/02/2022
  1935 00000B68 9C                  <1> 	pushfd
  1936 00000B69 0E                  <1> 	push	cs
  1937                              <1> 	;mov	ax, KDATA
  1938 00000B6A 31C0                <1> 	xor	eax, eax
  1939 00000B6C B010                <1> 	mov	al, KDATA
  1940 00000B6E 8ED8                <1> 	mov	ds, ax
  1941                              <1> 	;
  1942                              <1> 	;pushfd
  1943                              <1> 	;push	cs
  1944 00000B70 E810020000          <1> 	call	kb_int   ; int_09h
  1945                              <1> 	;
  1946 00000B75 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1947                              <1> 	;call	getc
  1948 00000B77 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1949 00000B7C 744E                <1> 	jz	short keyb_int4
  1950                              <1> 	;
  1951 00000B7E B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1952                              <1> 	;call	getc
  1953 00000B80 E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1954                              <1> 	;
  1955                              <1> 	; 20/02/2015
  1956 00000B85 0FB61D[266B0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1957                              <1> 	;
  1958 00000B8C 20C0                <1> 	and 	al, al
  1959 00000B8E 751D                <1> 	jnz	short keyb_int1
  1960                              <1> 	;
  1961 00000B90 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1962 00000B93 7218                <1> 	jb	short keyb_int1
  1963 00000B95 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1964 00000B98 7713                <1> 	ja	short keyb_int1
  1965                              <1> 	;
  1966 00000B9A 88D8                <1> 	mov	al, bl
  1967 00000B9C 0468                <1> 	add	al, 68h
  1968 00000B9E 38E0                <1> 	cmp	al, ah
  1969 00000BA0 7409                <1> 	je	short keyb_int0
  1970 00000BA2 88E0                <1> 	mov	al, ah
  1971 00000BA4 2C68                <1> 	sub	al, 68h
  1972 00000BA6 E83F0A0000          <1> 	call	tty_sw
  1973                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1974                              <1> keyb_int0: ; 30/06/2015
  1975                              <1> 	;xor	ax, ax
  1976                              <1> 	; 23/02/2022
  1977 00000BAB 31C0                <1> 	xor	eax, eax
  1978                              <1> keyb_int1:
  1979 00000BAD D0E3                <1> 	shl	bl, 1
  1980 00000BAF 81C3[286B0000]      <1> 	add	ebx, ttychr
  1981                              <1> 	;
  1982                              <1> 	;23/02/2022
  1983 00000BB5 09C0                <1> 	or	eax, eax
  1984                              <1> 	;or	ax, ax
  1985 00000BB7 7406                <1> 	jz	short keyb_int2
  1986                              <1> 	;
  1987 00000BB9 66833B00            <1> 	cmp 	word [ebx], 0
  1988 00000BBD 7703                <1>         ja      short keyb_int3 
  1989                              <1> keyb_int2:
  1990 00000BBF 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1991                              <1> 			   ; and scan code of the character
  1992                              <1> 			   ; for current tty (or last tty
  1993                              <1> 			   ; just before tty switch).
  1994                              <1> keyb_int3:
  1995 00000BC2 A0[266B0000]        <1>         mov     al, [ptty]
  1996 00000BC7 E8BE430000          <1> 	call	wakeup
  1997                              <1> 	;
  1998                              <1> keyb_int4:
  1999 00000BCC 58                  <1> 	pop	eax
  2000 00000BCD 5B                  <1> 	pop	ebx
  2001 00000BCE 1F                  <1> 	pop	ds
  2002 00000BCF CF                  <1> 	iret
  2003                              <1> 
  2004                              <1> ; 18/02/2015
  2005                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2006                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2007                              <1> ; scancode and ascii code of the character 
  2008                              <1> ; in the tty input (ttychr) buffer. 
  2009                              <1> ; Test procedures must call 'getch' for tty input
  2010                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2011                              <1> ; due to infinite (key press) waiting loop.
  2012                              <1> ; 
  2013                              <1> ; 03/12/2014
  2014                              <1> ; 26/08/2014
  2015                              <1> ; KEYBOARD I/O
  2016                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2017                              <1> 
  2018                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2019                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2020                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2021                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2022                              <1> 
  2023                              <1> int_16h: ; 30/06/2015
  2024                              <1> ;getc:
  2025 00000BD0 9C                  <1> 	pushfd	; 28/08/2014
  2026 00000BD1 0E                  <1> 	push 	cs
  2027 00000BD2 E826000000          <1> 	call 	getc_int
  2028 00000BD7 C3                  <1> 	retn
  2029                              <1> 
  2030                              <1> ; 24/12/2021
  2031                              <1> 
  2032                              <1> 	;-----	SHIFT STATUS
  2033                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2034 00000BD8 8A25[24650000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2035 00000BDE 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2036                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2037                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2038 00000BE1 C0E405              <1>         shl	ah, 5
  2039 00000BE4 A0[24650000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2040 00000BE9 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2041 00000BEB 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2042 00000BED A0[26650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2043 00000BF2 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2044 00000BF4 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2045                              <1> _K3:
  2046 00000BF6 A0[23650000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2047 00000BFB EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2048                              <1> 
  2049                              <1> getc_int:
  2050                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2051                              <1> 	; 28/02/2015
  2052                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2053                              <1> 	;	      instead of pc-at bios - 1985-)
  2054                              <1> 	; 28/08/2014 (_k1d)
  2055                              <1> 	; 30/06/2014
  2056                              <1> 	; 03/03/2014
  2057                              <1> 	; 28/02/2014
  2058                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2059                              <1> 	; rombios source code (21/04/1986)
  2060                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2061                              <1> 	;
  2062                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2063                              <1> 	;
  2064                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2065                              <1> 	; KEYBOARD I/O								      :
  2066                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2067                              <1> 	; INPUT									      :
  2068                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2069                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2070                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2071                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2072                              <1> 	;-----------------------------------------------------------------------------:
  2073                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2074                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2075                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2076                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2077                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2078                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2079                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2080                              <1> 	;-----------------------------------------------------------------------------:	
  2081                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2082                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2083                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2084                              <1> 	;-----------------------------------------------------------------------------:	
  2085                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2086                              <1> 	;	      (AL) = 05H                                                      :
  2087                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2088                              <1> 	;		       							      :
  2089                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2090                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2091                              <1> 	;                     --------------------------------------------            :
  2092                              <1> 	;			00H        30.0        10H        7.5                 :
  2093                              <1> 	;			01H        26.7        11H        6.7                 :
  2094                              <1> 	;			02H        24.0        12H        6.0                 :
  2095                              <1> 	;			03H        21.8        13H        5.5                 :
  2096                              <1> 	;			04H        20.0        14H        5.0                 :
  2097                              <1> 	;			05H        18.5        15H        4.6                 :
  2098                              <1> 	;			06H        17.1        16H        4.3                 :
  2099                              <1> 	;			07H        16.0        17H        4.0                 :
  2100                              <1> 	;			08H        15.0        18H        3.7                 :
  2101                              <1> 	;			09H        13.3        19H        3.3                 :
  2102                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2103                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2104                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2105                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2106                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2107                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2108                              <1> 	;									      :
  2109                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2110                              <1> 	;		       							      :
  2111                              <1> 	;                     REGISTER     DELAY                                      :
  2112                              <1> 	;                      VALUE       VALUE                                      :
  2113                              <1> 	;                     ------------------                                      :
  2114                              <1> 	;			00H        250 ms                                     :
  2115                              <1> 	;			01H        500 ms                                     :
  2116                              <1> 	;			02H        750 ms                                     :
  2117                              <1> 	;			03H       1000 ms                                     :
  2118                              <1> 	;-----------------------------------------------------------------------------:
  2119                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2120                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2121                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2122                              <1> 	;		           (CH) = SCAN CODE                                   :
  2123                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2124                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2125                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2126                              <1> 	;-----------------------------------------------------------------------------:		
  2127                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2128                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2129                              <1> 	;-----------------------------------------------------------------------------:
  2130                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2131                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2132                              <1> 	;-----------------------------------------------------------------------------:	
  2133                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2134                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2135                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2136                              <1> 	; OUTPUT					                              :
  2137                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2138                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2139                              <1> 	;------------------------------------------------------------------------------
  2140                              <1> 	
  2141 00000BFD FB                  <1> 	sti				; INTERRUPTS BACK ON
  2142 00000BFE 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2143 00000BFF 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2144                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2145 00000C00 66BB1000            <1>         mov     bx, KDATA 
  2146 00000C04 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2147 00000C06 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2148 00000C08 742D                <1> 	jz	short _K1		; ASCII_READ
  2149 00000C0A FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2150 00000C0C 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2151 00000C0E FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2152 00000C10 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2153 00000C12 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2154 00000C14 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2155 00000C16 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2156 00000C19 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2157                              <1> _KIO1:	
  2158 00000C1B 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2159 00000C1E 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2160 00000C20 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2161 00000C22 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2162 00000C24 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2163 00000C26 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2164                              <1> _KIO_EXIT:
  2165                              <1> 	;pop	ecx			; RECOVER REGISTER
  2166 00000C28 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2167 00000C29 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2168 00000C2A CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2169                              <1> 
  2170                              <1> 	;-----	ASCII CHARACTER
  2171                              <1> _K1E:	
  2172 00000C2B E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2173 00000C30 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2174 00000C35 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2175                              <1> _K1:	
  2176 00000C37 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2177 00000C3C E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2178 00000C41 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2179                              <1> _K1A:
  2180 00000C43 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2181                              <1> 
  2182                              <1> 	;-----	ASCII STATUS
  2183                              <1> _K2E:	
  2184 00000C45 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2185 00000C4A 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2186 00000C4C 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2187 00000C4D E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2188 00000C52 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2189                              <1> _K2:	
  2190 00000C54 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2191 00000C59 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2192 00000C5B 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2193 00000C5C E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2194 00000C61 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2195 00000C63 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2196 00000C64 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2197 00000C69 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2198                              <1> _K2A:
  2199 00000C6B 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2200                              <1> _K2B:
  2201                              <1> 	;pop	ecx			; RECOVER REGISTER
  2202 00000C6C 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2203 00000C6D 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2204 00000C6E CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2205                              <1> 
  2206                              <1> ; 24/12/2021
  2207                              <1> ;	;-----	SHIFT STATUS
  2208                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2209                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2210                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2211                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2212                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2213                              <1> ;       shl	ah, 5
  2214                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2215                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2216                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2217                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2218                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2219                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2220                              <1> ;_K3:
  2221                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2222                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2223                              <1> 
  2224                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2225                              <1> _K300:
  2226 00000C71 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2227 00000C73 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2228 00000C75 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2229 00000C78 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2230 00000C7A F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2231 00000C7D 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2232 00000C7F B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2233 00000C81 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2234                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2235                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2236 00000C86 C0E705              <1> 	shl	bh, 5
  2237 00000C89 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2238 00000C8B 08F8                <1> 	or	al, bh			; AND DELAY
  2239 00000C8D E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2240 00000C92 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2241                              <1> 
  2242                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2243                              <1> _K500:
  2244 00000C94 56                  <1> 	push	esi			; SAVE SI (esi)
  2245 00000C95 FA                  <1> 	cli				; 
  2246 00000C96 8B1D[34650000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2247 00000C9C 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2248 00000C9E E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2249 00000CA3 3B1D[30650000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2250 00000CA9 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2251 00000CAB 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2252 00000CAE 891D[34650000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2253 00000CB4 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2254 00000CB6 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2255                              <1> _K502:
  2256 00000CB8 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2257                              <1> _K504:
  2258 00000CBA FB                  <1> 	sti				
  2259 00000CBB 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2260 00000CBC E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2261                              <1> 
  2262                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2263                              <1> _K1S:
  2264 00000CC1 FA                  <1> 	cli	; 03/12/2014
  2265 00000CC2 8B1D[30650000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2266 00000CC8 3B1D[34650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2267                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2268 00000CCE 750F                <1> 	jne	short _k1x ; 03/12/2014
  2269                              <1> 	;
  2270                              <1> 	; 03/12/2014
  2271                              <1> 	; 28/08/2014
  2272                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2273                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2274                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2275                              <1> _K1T:                                   ; ASCII READ
  2276 00000CD0 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2277 00000CD1 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2278                              <1> _K1U:	
  2279 00000CD2 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2280 00000CD3 8B1D[30650000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2281 00000CD9 3B1D[34650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2282                              <1> _k1x:
  2283 00000CDF 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2284 00000CE0 9C                  <1> 	pushf				; SAVE FLAGS
  2285 00000CE1 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2286 00000CE6 8A1D[25650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2287 00000CEC 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2288 00000CEE 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2289 00000CF1 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2290 00000CF3 E86E060000          <1> 	call	SND_LED1
  2291 00000CF8 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2292                              <1> _K1V:
  2293 00000CF9 9D                  <1> 	popf				; RESTORE FLAGS
  2294 00000CFA 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2295 00000CFB 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2296                              <1> 	;
  2297 00000CFD 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2298 00000D00 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2299 00000D05 891D[30650000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2300 00000D0B C3                  <1> 	retn				; RETURN
  2301                              <1> 
  2302                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2303                              <1> _K2S:
  2304 00000D0C FA                  <1> 	cli				; INTERRUPTS OFF
  2305 00000D0D 8B1D[30650000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2306 00000D13 3B1D[34650000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2307 00000D19 668B03              <1> 	mov	ax, [ebx]
  2308 00000D1C 9C                  <1> 	pushf				; SAVE FLAGS
  2309                              <1> 	;push	ax			; SAVE CODE
  2310                              <1> 	; 24/12/2021
  2311 00000D1D 50                  <1> 	push	eax
  2312 00000D1E E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2313 00000D23 8A1D[25650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2314 00000D29 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2315 00000D2B 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2316 00000D2E 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2317 00000D30 E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2318                              <1> _K2T:
  2319                              <1> 	;pop	ax			; RESTORE CODE
  2320                              <1> 	; 24/12/2021
  2321 00000D35 58                  <1> 	pop	eax
  2322 00000D36 9D                  <1> 	popf				; RESTORE FLAGS
  2323 00000D37 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2324 00000D38 C3                  <1> 	retn				; RETURN
  2325                              <1> 
  2326                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2327                              <1> _KIO_E_XLAT:
  2328 00000D39 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2329 00000D3B 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2330 00000D3D 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2331 00000D3F 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2332 00000D41 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2333                              <1> _KIO_E_RET:				
  2334 00000D43 C3                  <1> 	retn				; GO BACK
  2335                              <1> 
  2336                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2337                              <1> _KIO_S_XLAT:
  2338 00000D44 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2339 00000D47 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2340 00000D49 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2341 00000D4B 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2342 00000D4D 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2343 00000D4F 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2344 00000D51 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2345                              <1> _kio_ret: ; 03/12/2014
  2346 00000D53 F8                  <1> 	clc
  2347 00000D54 C3                  <1> 	retn
  2348                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2349                              <1> _KIO_S1:				
  2350 00000D55 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2351                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2352 00000D57 C3                  <1> 	retn
  2353                              <1> _KIO_S2:		
  2354 00000D58 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2355 00000D5B 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2356 00000D5D 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2357 00000D5F 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2358 00000D61 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2359 00000D63 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2360 00000D65 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2361                              <1> _KIO_S3:
  2362 00000D67 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2363                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2364 00000D69 75E8                <1> 	jne	short _kio_ret
  2365 00000D6B 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2366 00000D6D 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2367 00000D6F 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2368                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2369                              <1> _KIO_USE:
  2370                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2371 00000D71 C3                  <1> 	retn				; RETURN	
  2372                              <1> _KIO_DIS:
  2373 00000D72 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2374 00000D73 C3                  <1> 	retn				; RETURN
  2375                              <1> 
  2376                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2377                              <1> _K4:    
  2378 00000D74 43                  <1> 	inc     ebx
  2379 00000D75 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2380 00000D76 3B1D[2C650000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2381                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2382 00000D7C 7206                <1> 	jb	short _K5
  2383 00000D7E 8B1D[28650000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2384                              <1> _K5:
  2385 00000D84 C3                  <1> 	retn
  2386                              <1> 
  2387                              <1> ; 20/02/2015
  2388                              <1> ; 05/12/2014
  2389                              <1> ; 26/08/2014
  2390                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2391                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2392                              <1> ;
  2393                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2394                              <1> ; rombios source code (06/10/1985)
  2395                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2396                              <1> 
  2397                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2398                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2399                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2400                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2401                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2402                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2403                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2404                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2405                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2406                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2407                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2408                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2409                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2410                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2411                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2412                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2413                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2414                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2415                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2416                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2417                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2418                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2419                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2420                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2421                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2422                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2423                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2424                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2425                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2426                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2427                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2428                              <1> F11_M		equ	87		; F11 KEY MAKE
  2429                              <1> F12_M		equ	88		; F12 KEY MAKE
  2430                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2431                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2432                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2433                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2434                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2435                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2436                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2437                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2438                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2439                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2440                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2441                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2442                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2443                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2444                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2445                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2446                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2447                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2448                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2449                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2450                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2451                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2452                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2453                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2454                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2455                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2456                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2457                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2458                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2459                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2460                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2461                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2462                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2463                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2464                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2465                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2466                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2467                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2468                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2469                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2470                              <1> ;
  2471                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2472                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2473                              <1> INTA00		equ	020h		; 8259 PORT
  2474                              <1> 
  2475                              <1> 
  2476                              <1> kb_int:
  2477                              <1> 
  2478                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2479                              <1> ; 17/10/2015 ('ctrlbrk') 
  2480                              <1> ; 05/12/2014
  2481                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2482                              <1> 	;	      instead of pc-at bios - 1985-)
  2483                              <1> ; 26/08/2014
  2484                              <1> ;
  2485                              <1> ; 03/06/86  KEYBOARD BIOS
  2486                              <1> ;
  2487                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2488                              <1> ;										;
  2489                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2490                              <1> ;										;
  2491                              <1> ;--------------------------------------------------------------------------------
  2492                              <1> 
  2493                              <1> KB_INT_1:
  2494 00000D85 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2495                              <1> 	;push	ebp
  2496 00000D86 50                  <1> 	push	eax
  2497 00000D87 53                  <1> 	push	ebx
  2498 00000D88 51                  <1> 	push	ecx
  2499 00000D89 52                  <1> 	push	edx
  2500 00000D8A 56                  <1> 	push	esi
  2501 00000D8B 57                  <1> 	push	edi
  2502 00000D8C 1E                  <1> 	push	ds
  2503 00000D8D 06                  <1> 	push	es
  2504 00000D8E FC                  <1> 	cld				; FORWARD DIRECTION
  2505 00000D8F 66B81000            <1> 	mov	ax, KDATA
  2506 00000D93 8ED8                <1> 	mov	ds, ax
  2507 00000D95 8EC0                <1> 	mov	es, ax
  2508                              <1> 	;
  2509                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2510 00000D97 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2511 00000D99 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2512 00000D9E FA                  <1> 	cli				; DISABLE INTERRUPTS
  2513 00000D9F B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2514                              <1> KB_INT_01:
  2515 00000DA4 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2516 00000DA6 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2517 00000DA8 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2518                              <1> 	;
  2519                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2520 00000DAA E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2521                              <1> 	;
  2522                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2523                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2524                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2525                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2526                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2527                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2528                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2529                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2530                              <1> 	;
  2531                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2532                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2533 00000DAC FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2534 00000DAD 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2535 00000DAF 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2536                              <1> 	;
  2537                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2538 00000DB1 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2539 00000DB3 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2540                              <1> 	;
  2541                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2542 00000DB5 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2543 00000DB6 800D[25650000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2544 00000DBD E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2545                              <1> 	;
  2546                              <1> 	;-----	RESEND THE LAST BYTE
  2547                              <1> KB_INT_4:
  2548 00000DC2 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2549 00000DC3 800D[25650000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2550 00000DCA E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2551                              <1> 	;
  2552                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2553                              <1> KB_INT_2:
  2554                              <1> 	;push 	ax			; SAVE DATA IN
  2555                              <1> 	; 24/12/2021
  2556 00000DCF 50                  <1> 	push	eax
  2557 00000DD0 E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2558 00000DD5 8A1D[25650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2559 00000DDB 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2560 00000DDD 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2561 00000DE0 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2562 00000DE2 E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2563                              <1> UP0:
  2564                              <1> 	;pop	ax			; RESTORE DATA IN
  2565                              <1> 	; 24/12/2021
  2566 00000DE7 58                  <1> 	pop	eax
  2567                              <1> ;------------------------------------------------------------------------
  2568                              <1> ;	START OF KEY PROCESSING						;
  2569                              <1> ;------------------------------------------------------------------------
  2570 00000DE8 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2571                              <1> 	;
  2572                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2573 00000DEA 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2574                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2575                              <1> 	; 24/12/2021
  2576 00000DEC 7505                <1> 	jne	short K16
  2577 00000DEE E9ED040000          <1> 	jmp	K62
  2578                              <1> K16:	
  2579 00000DF3 8A3D[26650000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2580                              <1> 	;
  2581                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2582 00000DF9 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2583 00000DFC 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2584 00000DFE 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2585 00000E00 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2586 00000E02 7507                <1> 	jne	short RST_RD_ID
  2587 00000E04 800D[26650000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2588                              <1> RST_RD_ID:
  2589 00000E0B 8025[26650000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2590 00000E12 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2591                              <1> 	; 24/12/2021
  2592                              <1> 	;jmp	K26
  2593                              <1> 	;
  2594                              <1> TST_ID_2:
  2595 00000E14 8025[26650000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2596 00000E1B 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2597 00000E1D 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2598 00000E1F 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2599 00000E21 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2600                              <1> 	; 24/12/2021
  2601                              <1> 	;jne	K26
  2602                              <1> 	;
  2603                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2604 00000E23 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2605 00000E26 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2606 00000E28 800D[23650000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2607 00000E2F E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2608                              <1> KX_BIT:
  2609 00000E34 800D[26650000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2610 00000E3B E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2611                              <1> 	;
  2612                              <1> NOT_ID:
  2613 00000E40 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2614 00000E42 750E                <1> 	jne	short TEST_E1
  2615 00000E44 800D[26650000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2616 00000E4B EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2617                              <1> 	; 24/12/2021
  2618 00000E4D E9DA010000          <1> 	jmp	K26A	
  2619                              <1> TEST_E1:	
  2620 00000E52 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2621 00000E54 750C                <1> 	jne	short NOT_HC
  2622 00000E56 800D[26650000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2623 00000E5D E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2624                              <1> 	;
  2625                              <1> NOT_HC:
  2626 00000E62 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2627 00000E64 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2628 00000E67 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2629                              <1> 	;
  2630 00000E69 BF[0E640000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2631 00000E6E AE                  <1> 	scasb
  2632                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2633                              <1> 	; 24/12/2021
  2634 00000E6F 7458                <1> 	je	short K16B
  2635 00000E71 AE                  <1> 	scasb
  2636 00000E72 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2637 00000E74 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2638                              <1> 	; 24/12/2021
  2639                              <1> 	;jmp	K26
  2640                              <1> 	;
  2641                              <1> NOT_LC_E0:
  2642 00000E76 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2643 00000E79 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2644 00000E7B B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2645 00000E80 BF[0C640000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2646 00000E85 F2AE                <1> 	repne	scasb			; CHECK IT
  2647 00000E87 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2648                              <1> 	; 24/12/2021
  2649                              <1> 	;je	K26A			
  2650                              <1> 	;
  2651 00000E89 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2652 00000E8B 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2653                              <1> 	; 24/12/2021
  2654                              <1> 	;jne	K26
  2655 00000E8D F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2656 00000E90 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2657                              <1> 	; 24/12/2021
  2658                              <1> 	;jnz	K26
  2659                              <1>         ; 20/02/2015 
  2660 00000E92 F605[24650000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2661 00000E99 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2662                              <1> 	; 24/12/2021
  2663                              <1> 	;jnz	K26
  2664 00000E9B E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2665                              <1> 	;
  2666                              <1> 	;-----	TEST FOR SYSTEM KEY
  2667                              <1> T_SYS_KEY:
  2668 00000EA0 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2669 00000EA2 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2670                              <1> 	;
  2671 00000EA4 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2672 00000EA7 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2673                              <1> 	;
  2674 00000EA9 F605[24650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2675 00000EB0 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2676                              <1> 	;jnz	K26			
  2677                              <1> 	;
  2678 00000EB2 800D[24650000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2679 00000EB9 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2680 00000EBB E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2681                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2682 00000EBD B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2683 00000EBF E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2684                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2685                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2686                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2687                              <1> 	;INT	15H			; USER INTERRUPT	
  2688 00000EC4 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2689                              <1> 	;
  2690 00000EC9 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2691                              <1> 	;
  2692                              <1> K16C:
  2693 00000ECE 8025[24650000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2694 00000ED5 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2695 00000ED7 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2696                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2697                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2698                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2699                              <1> 	;
  2700                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2701                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2702                              <1> 	;INT	15H			; USER INTERRUPT
  2703                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2704                              <1> 	;
  2705 00000ED9 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2706                              <1> 	;
  2707                              <1> 	;-----	TEST FOR SHIFT KEYS
  2708                              <1> K16A:
  2709 00000EDE 8A1D[23650000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2710 00000EE4 BF[08640000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2711 00000EE9 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2712 00000EEE F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2713 00000EF0 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2714                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2715                              <1> 	; 24/12/2021
  2716 00000EF2 7405                <1> 	je	short K17
  2717 00000EF4 E914010000          <1> 	jmp	K25
  2718                              <1> 	;
  2719                              <1> 	;------	SHIFT KEY FOUND
  2720                              <1> K17:
  2721 00000EF9 81EF[09640000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2722 00000EFF 8AA7[10640000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2723 00000F05 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2724 00000F07 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2725                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2726                              <1> 	; 24/12/2021
  2727 00000F09 7405                <1> 	jz	short K17C
  2728 00000F0B E999000000          <1> 	jmp	K23
  2729                              <1> 	;
  2730                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2731                              <1> K17C:
  2732 00000F10 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2733 00000F13 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2734                              <1> 	;
  2735                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2736 00000F15 0825[23650000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2737 00000F1B A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2738 00000F1D 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2739                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2740                              <1> 	; 24/12/2021
  2741 00000F1F E901010000          <1> 	jmp	K26
  2742                              <1> K17D:
  2743 00000F24 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2744 00000F27 740B                <1> 	jz 	short K17E		; NO, JUMP
  2745 00000F29 0825[26650000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2746 00000F2F E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2747                              <1> K17E:
  2748 00000F34 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2749 00000F36 0825[24650000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2750 00000F3C E9E4000000          <1> 	jmp	K26
  2751                              <1> 	;
  2752                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2753                              <1> K18:					; SHIFT-TOGGLE
  2754 00000F41 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2755 00000F44 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2756                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2757                              <1> 	; 24/12/2021
  2758 00000F46 E9C2000000          <1> 	jmp	K25
  2759                              <1> K18A:
  2760 00000F4B 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2761 00000F4D 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2762 00000F4F F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2763 00000F52 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2764                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2765                              <1> 	; 24/12/2021
  2766 00000F54 E9B4000000          <1> 	jmp	K25
  2767                              <1> K18B:
  2768 00000F59 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2769 00000F5C 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2770                              <1> K19:	
  2771 00000F5E F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2772 00000F61 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2773 00000F63 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2774 00000F66 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2775                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2776 00000F68 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2777 00000F6A E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2778                              <1> K21:					; MIGHT BE NUMERIC
  2779 00000F6F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2780 00000F72 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2781                              <1> 	;
  2782                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2783 00000F74 8425[24650000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2784                              <1> 	;jnz	K26
  2785                              <1> 	; 24/12/2021
  2786 00000F7A 7405                <1> 	jz	short K22A
  2787 00000F7C E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2788                              <1> K22A:
  2789 00000F81 0825[24650000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2790 00000F87 3025[23650000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2791                              <1> 	;
  2792                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2793 00000F8D F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2794 00000F90 7407                <1> 	jz	short K22B		; GO IF NOT
  2795                              <1> 	;
  2796                              <1> 	; 24/12/2021
  2797                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2798 00000F92 50                  <1> 	push	eax
  2799 00000F93 E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2800                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2801 00000F98 58                  <1> 	pop	eax
  2802                              <1> K22B:
  2803 00000F99 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2804                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2805                              <1> 	; 24/12/2021
  2806 00000F9B 7405                <1> 	je	short K22C
  2807 00000F9D E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2808                              <1> K22C:
  2809 00000FA2 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2810 00000FA4 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2811                              <1> 	;
  2812                              <1> 	;-----	BREAK SHIFT FOUND
  2813                              <1> K23:					; BREAK-SHIFT-FOUND
  2814 00000FA9 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2815 00000FAC F6D4                <1> 	not	ah			; INVERT MASK
  2816 00000FAE 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2817 00000FB0 2025[23650000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2818 00000FB6 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2819 00000FB9 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2820                              <1> 	;
  2821 00000FBB F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2822 00000FBE 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2823 00000FC0 2025[26650000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2824 00000FC6 EB08                <1> 	jmp	short K23B		; CONTINUE
  2825                              <1> K23A:
  2826 00000FC8 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2827 00000FCA 2025[24650000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2828                              <1> K23B:
  2829 00000FD0 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2830 00000FD2 A0[26650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2831 00000FD7 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2832 00000FD9 0A05[24650000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2833 00000FDF D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2834 00000FE1 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2835 00000FE3 0805[23650000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2836 00000FE9 88E0                <1> 	mov	al, ah
  2837                              <1> K23D:
  2838 00000FEB 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2839 00000FED 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2840                              <1> 	;	
  2841                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2842 00000FEF A0[27650000]        <1> 	mov	al, [ALT_INPUT]
  2843 00000FF4 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2844 00000FF6 8825[27650000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2845 00000FFC 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2846 00000FFE 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2847 00001000 E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2848                              <1> 	;
  2849                              <1> K24:					; BREAK-TOGGLE
  2850 00001005 2025[24650000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2851 0000100B EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2852                              <1> 	;
  2853                              <1> 	;-----	TEST FOR HOLD STATE
  2854                              <1> 					; AL, AH = SCAN CODE
  2855                              <1> K25:					; NO-SHIFT-FOUND
  2856 0000100D 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2857 0000100F 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2858 00001011 F605[24650000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2859 00001018 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2860 0000101A 3C45                <1> 	cmp	al, NUM_KEY
  2861 0000101C 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2862 0000101E 8025[24650000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2863                              <1> 	;
  2864                              <1> K26:
  2865 00001025 8025[26650000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2866                              <1> K26A:					; INTERRUPT-RETURN
  2867 0000102C FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2868 0000102D B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2869 0000102F E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2870                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2871 00001031 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2872 00001033 E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2873                              <1> K27A:
  2874 00001038 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2875 00001039 07                  <1> 	pop	es			; RESTORE REGISTERS
  2876 0000103A 1F                  <1> 	pop	ds
  2877 0000103B 5F                  <1> 	pop	edi
  2878 0000103C 5E                  <1> 	pop	esi
  2879 0000103D 5A                  <1> 	pop	edx
  2880 0000103E 59                  <1> 	pop	ecx
  2881 0000103F 5B                  <1> 	pop	ebx
  2882 00001040 58                  <1> 	pop	eax
  2883                              <1> 	;pop	ebp
  2884 00001041 CF                  <1> 	iret				; RETURN
  2885                              <1> 
  2886                              <1> 	;-----	NOT IN	HOLD STATE
  2887                              <1> K28:					; NO-HOLD-STATE
  2888 00001042 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2889 00001044 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2890                              <1> 	;
  2891 00001046 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2892 00001049 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2893                              <1>         ; 24/12/2021
  2894                              <1> 	;jz      K38
  2895                              <1> 	;
  2896 0000104B F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2897 0000104E 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2898                              <1> 	; 28/02/2015
  2899 00001050 F605[24650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2900 00001057 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2901                              <1> 	; 24/12/2021
  2902                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2903                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2904 00001059 E9D1000000          <1> K28A:	jmp	K38
  2905                              <1> 	;
  2906                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2907                              <1> K29:					; TEST-RESET
  2908 0000105E F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2909 00001061 740B                <1> 	jz	short K31		; NO_RESET
  2910 00001063 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2911 00001065 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2912                              <1> 	;
  2913                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2914                              <1>  	; 26/08/2014
  2915                              <1> cpu_reset:
  2916                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2917                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2918 00001067 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2919 00001069 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2920                              <1> khere:
  2921 0000106B F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2922 0000106C EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2923                              <1> 
  2924                              <1> 	;
  2925                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2926                              <1> K31:					; NO-RESET
  2927 0000106E 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2928 00001070 7507                <1> 	jne	short K311		; NOT THERE
  2929 00001072 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2930 00001074 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2931                              <1> K311:
  2932 00001079 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2933 0000107B 7509                <1> 	jne	short K312		; NOT THERE
  2934 0000107D 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2935 00001081 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2936                              <1> K312:
  2937 00001086 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2938 00001088 7471                <1>         je	short K37B              ; GO PROCESS
  2939 0000108A 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2940 0000108C 746D                <1>         je	short K37B              ; GO PROCESS
  2941                              <1> 	;
  2942                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2943                              <1> K32:					; ALT-KEY-PAD
  2944 0000108E BF[E4630000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2945 00001093 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2946 00001098 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2947 0000109A 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2948 0000109C F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2949                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2950                              <1> 	; 24/12/2021
  2951 0000109F 751C                <1> 	jnz	short K32B
  2952 000010A1 81EF[E5630000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2953 000010A7 A0[27650000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2954 000010AC B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2955 000010AE F6E4                <1> 	mul	ah
  2956 000010B0 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2957 000010B3 A2[27650000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2958                              <1> K32A:
  2959 000010B8 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2960                              <1> K32B:
  2961                              <1> 	; 24/12/2021
  2962 000010BD EB6A                <1> 	jmp	K37C
  2963                              <1> 	;
  2964                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2965                              <1> K33:					; NO-ALT-KEYPAD
  2966 000010BF C605[27650000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2967 000010C6 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2968 000010CB F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2969 000010CD 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2970                              <1> 	;
  2971                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2972                              <1> K34:					; ALT-TOP-ROW
  2973 000010CF 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2974 000010D1 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2975 000010D3 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2976 000010D5 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2977 000010D7 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2978 000010DA EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2979                              <1> 	;
  2980                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2981                              <1> K35:					; ALT-FUNCTION
  2982 000010DC 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2983 000010DE 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2984 000010E0 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2985 000010E2 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2986 000010E4 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2987 000010E7 EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2988                              <1> K35A:
  2989 000010E9 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2990 000010EC 7425                <1> 	jz	short K37		; NO, JUMP
  2991 000010EE 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2992 000010F0 7510                <1>         jne     short K35B              ; NOT THERE
  2993 000010F2 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2994 000010F6 E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2995                              <1> K37B:
  2996 000010FB B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2997 000010FD E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2998                              <1> K35B:
  2999 00001102 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3000 00001104 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3001 00001106 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3002 00001108 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3003                              <1>         ; 24/12/2021
  3004                              <1> 	;jne	K26
  3005 0000110A 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3006 0000110E E99C010000          <1> 	jmp	K57			; BUFFER FILL
  3007                              <1> K37:
  3008 00001113 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3009 00001115 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3010 00001117 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3011                              <1>         ;ja	short K32A		; IF SO, IGNORE
  3012 00001119 0F8706FFFFFF        <1>         ja      K26
  3013 0000111F 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3014                              <1> K37A:
  3015 00001122 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3016 00001124 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3017                              <1> K37C:
  3018 00001129 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3019 0000112B 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3020 0000112D EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3021                              <1> 	;
  3022                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3023                              <1> K38:					; NOT-ALT-SHIFT
  3024                              <1> 					; BL STILL HAS SHIFT FLAGS
  3025 0000112F F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3026 00001132 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3027                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3028                              <1> 	; 24/12/2021
  3029 00001134 E9AB000000          <1> 	jmp	K44
  3030                              <1> 	;
  3031                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3032                              <1> 	;-----	TEST FOR BREAK
  3033                              <1> K38A:
  3034 00001139 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3035 0000113B 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3036 0000113D F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3037 00001140 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3038 00001142 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3039 00001145 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3040                              <1> K38B:
  3041 00001147 8B1D[30650000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3042 0000114D 891D[34650000]      <1> 	mov	[BUFFER_TAIL], ebx
  3043 00001153 C605[22650000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3044                              <1> 	;
  3045                              <1> 	;-----	ENABLE KEYBOARD
  3046 0000115A B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3047 0000115C E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3048                              <1> 	;
  3049                              <1> 	; CTRL+BREAK code here !!!
  3050                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3051                              <1> 	; 17/10/2015	
  3052 00001161 E85C220000          <1> 	call	ctrlbrk ; control+break subroutine
  3053                              <1> 	;
  3054                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3055                              <1> 	; 24/12/2021
  3056 00001166 29C0                <1> 	sub	eax, eax
  3057 00001168 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3058                              <1> 	;
  3059                              <1> 	;-----	TEST FOR PAUSE
  3060                              <1> K39:					; NO_BREAK
  3061 0000116D F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3062 00001170 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3063 00001172 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3064 00001174 7533                <1> 	jne	short K41		; NO-PAUSE
  3065                              <1> K39P:
  3066 00001176 800D[24650000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3067                              <1> 	;
  3068                              <1> 	;-----	ENABLE KEYBOARD
  3069 0000117D B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3070 0000117F E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3071                              <1> K39A:
  3072 00001184 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3073 00001186 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3074                              <1> 	;
  3075                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3076 00001188 803D[20650000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3077 0000118F 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3078 00001191 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3079 00001195 A0[21650000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3080 0000119A EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3081                              <1> 	;
  3082                              <1> K40:					; PAUSE-LOOP
  3083 0000119B F605[24650000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3084 000011A2 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3085                              <1> 	;
  3086 000011A4 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3087                              <1>         ;
  3088                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3089                              <1> K41:					; NO-PAUSE
  3090 000011A9 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3091 000011AB 7513                <1> 	jne	short K42		; NOT-KEY-55
  3092 000011AD F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3093 000011B0 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3094 000011B2 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3095 000011B5 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3096                              <1> K41A:	
  3097 000011B7 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3098 000011BB E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3099                              <1> 	;
  3100                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3101                              <1> K42:					; NOT-KEY-55
  3102 000011C0 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3103 000011C2 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3104 000011C4 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3105 000011C6 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3106 000011C8 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3107 000011CB 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3108 000011CD 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3109 000011D1 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3110                              <1> K42A:
  3111                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3112 000011D6 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3113                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3114                              <1> 	;;jb	K56 ; 20/02/2015
  3115                              <1> 	;;jmp	K64 ; 20/02/2015
  3116                              <1> K42B:
  3117 000011D8 BB[18640000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3118                              <1> 	;;jmp	K64
  3119                              <1> 	;jb	K56 ;; 20/02/2015	
  3120                              <1> 	; 24/12/2021
  3121 000011DD 7267                <1> 	jb	short K45F
  3122 000011DF E9B9000000          <1> 	jmp	K64	
  3123                              <1>         ;
  3124                              <1> 	;-----	NOT IN CONTROL SHIFT
  3125                              <1> K44:					; NOT-CTL-SHIFT
  3126 000011E4 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3127 000011E6 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3128 000011E8 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3129 000011EB 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3130 000011ED F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3131 000011F0 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3132 000011F2 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3133                              <1> K44A:
  3134 000011F4 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3135 000011F7 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3136                              <1> 	;
  3137                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3138                              <1> K44B:
  3139 000011F9 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3140 000011FB E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3141 00001200 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3142 00001202 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3143                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3144                              <1> 	;PUSH 	BP			; SAVE POINTER
  3145                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3146                              <1> 	;POP	BP			; RESTORE POINTER
  3147 00001204 8025[26650000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3148 0000120B E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3149                              <1> 	;
  3150                              <1> 	;-----	HANDLE IN-CORE KEYS
  3151                              <1> K45:					; NOT-PRINT-SCREEN
  3152 00001210 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3153 00001212 7734                <1> 	ja	short K46		; JUMP IF NOT
  3154 00001214 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3155 00001216 7505                <1> 	jne	short K45A		; NO, JUMP
  3156 00001218 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3157 0000121B 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3158                              <1> K45A:
  3159 0000121D B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3160 00001222 BF[EE630000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3161 00001227 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3162                              <1> 		; 20/02/2015
  3163 00001229 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3164                              <1> 	;
  3165 0000122B F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3166 0000122E 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3167                              <1> K45B:
  3168 00001230 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3169 00001233 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3170                              <1> 					; NO, LOWERCASE
  3171                              <1> K45C:
  3172 00001235 BB[70640000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3173 0000123A EB51                <1> 	jmp	short K56	
  3174                              <1> K45D:					; ALMOST-CAPS-STATE
  3175 0000123C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3176 0000123F 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3177                              <1> K45E:
  3178 00001241 BB[C8640000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3179 00001246 EB45                <1> K45F:	jmp	short K56
  3180                              <1> 	;
  3181                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3182                              <1> K46:					; NOT IN-CORE AREA
  3183 00001248 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3184                              <1> 	;ja	short K47		; JUMP IF NOT
  3185                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3186 0000124A 7635                <1> 	jna	short K53		
  3187                              <1> 	;
  3188                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3189                              <1> K47:					; NOT F1 - F10
  3190 0000124C 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3191 0000124E 772D                <1> 	ja	short K52		; JUMP IF NOT
  3192                              <1> 	;
  3193                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3194                              <1> K48:
  3195 00001250 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3196 00001252 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3197 00001254 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3198 00001256 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3199 00001258 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3200 0000125B 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3201                              <1> 	;		
  3202 0000125D F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3203 00001260 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3204 00001262 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3205                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3206 00001265 75DA                <1> 	jnz	short K45E
  3207                              <1> 	;
  3208                              <1> 	;-----	BASE CASE FOR KEYPAD
  3209                              <1> K49:					
  3210 00001267 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3211 00001269 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3212 0000126B B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3213 0000126D EB40                <1> 	jmp	short K57		; BUFFER FILL
  3214                              <1> K49A:
  3215 0000126F BB[70640000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3216 00001274 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3217                              <1> 	;
  3218                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3219                              <1> K50:					; ALMOST-NUM-STATE
  3220 00001276 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3221 00001279 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3222 0000127B EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3223                              <1> 	;
  3224                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3225                              <1> K52:					; NOT A NUMPAD KEY
  3226 0000127D 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3227                              <1> 	;jne	short K53		; JUMP IF NOT
  3228                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3229 0000127F 74AF                <1> 	je	short K45B		
  3230                              <1> 	;
  3231                              <1> 	;-----	MUST BE F11 OR F12 
  3232                              <1> K53:					; F1 - F10 COME HERE, TOO
  3233 00001281 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3234 00001284 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3235                              <1> 		; 20/02/2015 
  3236 00001286 BB[C8640000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3237 0000128B EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3238                              <1> 	;
  3239                              <1> 	;-----	TRANSLATE THE CHARACTER
  3240                              <1> K56:					; TRANSLATE-CHAR
  3241 0000128D FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3242 0000128F D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3243 00001290 F605[26650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3244 00001297 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3245 00001299 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3246 0000129B EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3247                              <1> 	;
  3248                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3249                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3250 0000129D FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3251 0000129F D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3252 000012A0 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3253 000012A2 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3254 000012A4 F605[26650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3255 000012AB 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3256 000012AD B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3257                              <1> 	;
  3258                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3259                              <1> K57:					; BUFFER_FILL
  3260 000012AF 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3261 000012B1 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3262                              <1> 	; 24/12/2021
  3263                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3264 000012B3 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3265                              <1> 	; 24/12/2021
  3266 000012B6 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3267                              <1> 	;je	K26			; INTERRUPT_RETURN
  3268                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3269 000012B8 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3270                              <1> K61:					; NOT-CAPS-STATE
  3271 000012BD 8B1D[34650000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3272 000012C3 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3273 000012C5 E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3274 000012CA 3B1D[30650000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3275 000012D0 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3276 000012D2 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3277 000012D5 891D[34650000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3278 000012DB E945FDFFFF          <1> 	jmp	K26
  3279                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3280                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3281                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3282                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3283                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3284                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3285                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3286                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3287                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3288                              <1> 	;;jmp   K27                    
  3289                              <1> 	;
  3290                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3291                              <1> K62:
  3292 000012E0 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3293 000012E2 E620                <1> 	out	INTA00, al
  3294 000012E4 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3295 000012E8 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3296 000012EA E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3297 000012EF E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3298                              <1> 
  3299                              <1> SHIP_IT:
  3300                              <1> 	;---------------------------------------------------------------------------------
  3301                              <1> 	; SHIP_IT
  3302                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3303                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3304                              <1> 	;---------------------------------------------------------------------------------
  3305                              <1> 	;
  3306                              <1> 	;push	ax			; SAVE DATA TO SEND
  3307                              <1> 	; 24/12/2021
  3308 000012F4 50                  <1> 	push	eax
  3309                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3310 000012F5 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3311                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3312 000012F6 B900000100          <1> 	mov	ecx, 10000h			
  3313                              <1> S10:
  3314 000012FB E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3315 000012FD A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3316 000012FF E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3317                              <1> 
  3318                              <1> 	;pop	ax			; GET DATA TO SEND
  3319                              <1> 	; 24/12/2021
  3320 00001301 58                  <1> 	pop	eax
  3321 00001302 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3322 00001304 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3323 00001305 C3                  <1> 	retn				; RETURN TO CALLER
  3324                              <1> 
  3325                              <1> SND_DATA:
  3326                              <1> 	; ---------------------------------------------------------------------------------
  3327                              <1> 	; SND_DATA
  3328                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3329                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3330                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3331                              <1> 	; ---------------------------------------------------------------------------------
  3332                              <1> 	;
  3333                              <1> 	;push	ax			; SAVE REGISTERS
  3334                              <1> 	;push	bx
  3335                              <1> 	; 24/12/2021
  3336 00001306 50                  <1> 	push	eax
  3337 00001307 53                  <1> 	push	ebx
  3338 00001308 51                  <1> 	push	ecx
  3339 00001309 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3340 0000130B B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3341                              <1> SD0:
  3342 0000130D FA                  <1> 	cli				; DISABLE INTERRUPTS
  3343 0000130E 8025[25650000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3344                              <1> 	;
  3345                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3346 00001315 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3347                              <1> SD5:
  3348 0000131A E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3349 0000131C A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3350 0000131E E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3351                              <1> 	;
  3352 00001320 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3353 00001322 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3354 00001324 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3355                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3356 00001325 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3357                              <1> SD1:
  3358 0000132A F605[25650000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3359 00001331 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3360 00001333 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3361                              <1> SD2:
  3362 00001335 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3363 00001337 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3364 00001339 800D[25650000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3365 00001340 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3366                              <1> SD3:
  3367 00001342 F605[25650000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3368 00001349 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3369                              <1> SD4:	
  3370 0000134B 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3371                              <1> 	;pop	bx
  3372                              <1> 	;pop	ax
  3373                              <1> 	; 24/12/2021
  3374 0000134C 5B                  <1> 	pop	ebx
  3375 0000134D 58                  <1> 	pop	eax
  3376 0000134E C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3377                              <1> 
  3378                              <1> SND_LED:
  3379                              <1> 	; ---------------------------------------------------------------------------------
  3380                              <1> 	; SND_LED
  3381                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3382                              <1> 	;
  3383                              <1> 	;----------------------------------------------------------------------------------
  3384                              <1> 	;
  3385 0000134F FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3386 00001350 F605[25650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3387 00001357 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3388                              <1> 	;
  3389 00001359 800D[25650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3390 00001360 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3391 00001362 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3392 00001364 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3393                              <1> SND_LED1:
  3394 00001366 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3395 00001367 F605[25650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3396 0000136E 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3397                              <1> 	;
  3398 00001370 800D[25650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3399                              <1> SL0:
  3400 00001377 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3401 00001379 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3402 0000137E FA                  <1> 	cli
  3403 0000137F E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3404 00001384 8025[25650000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3405 0000138B 0805[25650000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3406 00001391 F605[25650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3407 00001398 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3408                              <1> 	;
  3409 0000139A E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3410 0000139F FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3411 000013A0 F605[25650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3412 000013A7 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3413                              <1> SL2:
  3414 000013A9 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3415 000013AB E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3416 000013B0 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3417                              <1> SL3:
  3418 000013B1 8025[25650000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3419                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3420 000013B8 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3421 000013B9 C3                  <1> 	retn				; RETURN TO CALLER
  3422                              <1> 
  3423                              <1> MAKE_LED:
  3424                              <1> 	;---------------------------------------------------------------------------------
  3425                              <1> 	; MAKE_LED
  3426                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3427                              <1> 	;	THE MODE INDICATORS.
  3428                              <1> 	;---------------------------------------------------------------------------------
  3429                              <1> 	;
  3430                              <1> 	;push 	cx			; SAVE CX
  3431 000013BA A0[23650000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3432 000013BF 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3433                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3434                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3435 000013C1 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3436 000013C4 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3437                              <1> 	;pop	cx
  3438 000013C6 C3                  <1> 	retn				; RETURN TO CALLER
  3439                              <1> 
  3440                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3441                              <1> 
  3442                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1866                                  
  1867                                  %include 'video.inc' ; 07/03/2015
  1868                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1869                              <1> ; Last Modification: 26/02/2022
  1870                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1871                              <1> ;
  1872                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1873                              <1> 
  1874                              <1> ; 07/02/2022
  1875                              <1> ; 02/02/2022 (simplified scroll up)
  1876                              <1> ; 16/01/2016
  1877                              <1> ; 30/06/2015
  1878                              <1> ; 27/06/2015
  1879                              <1> ; 11/03/2015
  1880                              <1> ; 02/09/2014
  1881                              <1> ; 30/08/2014
  1882                              <1> ; VIDEO FUNCTIONS
  1883                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1884                              <1> 
  1885                              <1> write_tty:
  1886                              <1> 	; 02/02/2022
  1887                              <1> 	; 13/08/2015
  1888                              <1> 	; 02/09/2014
  1889                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1890                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1891                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1892                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1893                              <1> 	;
  1894                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1895                              <1> 	;	   AL = Character to be written
  1896                              <1> 	;	   EBX = Video Page (0 to 7)
  1897                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1898                              <1> 
  1899                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1900                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1901                              <1> 
  1902                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1903                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1904                              <1> ;
  1905                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1906                              <1> ;
  1907                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1908                              <1> ;										:
  1909                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1910                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1911                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1912                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1913                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1914                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1915                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1916                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1917                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1918                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1919                              <1> ;   THE 0 COLOR IS USED.							:
  1920                              <1> ;   ENTRY --									:
  1921                              <1> ;     (AH) = CURRENT CRT MODE							:
  1922                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1923                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1924                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1925                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1926                              <1> ;   EXIT -- 									:
  1927                              <1> ;     ALL REGISTERS SAVED							:
  1928                              <1> ;--------------------------------------------------------------------------------
  1929                              <1> 
  1930 000013C7 FA                  <1> 	cli
  1931                              <1> 	;
  1932                              <1> 	; READ CURSOR (04/12/2013)
  1933                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1934 000013C8 08FF                <1> 	or	bh, bh
  1935                              <1> 	;jnz	beeper
  1936                              <1> 	; 02/02/2022
  1937 000013CA 7405                <1> 	jz	short u14
  1938 000013CC E992000000          <1> 	jmp	beeper
  1939                              <1> u14:
  1940                              <1> 	; 02/02/2022
  1941                              <1> 	;; 01/09/2014
  1942                              <1> 	;cmp	byte [CRT_MODE], 3
  1943                              <1> 	;je	short m3
  1944                              <1> 	;;
  1945                              <1> 	;call	set_mode
  1946                              <1> m3:
  1947 000013D1 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1948                              <1> 	;shl	si, 1
  1949                              <1> 	; 02/02/2022
  1950 000013D3 D1E6                <1> 	shl	esi, 1
  1951 000013D5 81C6[166B0000]      <1> 	add	esi, cursor_posn
  1952 000013DB 668B16              <1> 	mov	dx, [esi]
  1953                              <1> 	;
  1954                              <1> 	; dx now has the current cursor position
  1955                              <1> 	;
  1956 000013DE 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1957 000013E0 7647                <1> 	jbe	short u8
  1958                              <1> 	;
  1959                              <1> 	; write the char to the screen
  1960                              <1> u0:	
  1961                              <1> 	; ah = attribute/color
  1962                              <1> 	; al = character
  1963                              <1> 	; bl = video page number (0 to 7)
  1964                              <1> 	; bh = 0
  1965                              <1> 	;
  1966 000013E2 E8D6010000          <1> 	call	write_c_current
  1967                              <1> 	;
  1968                              <1> 	; position the cursor for next char
  1969 000013E7 FEC2                <1> 	inc	dl		; next column
  1970                              <1> 	;cmp	dl, [CRT_COLS]
  1971 000013E9 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1972                              <1>         ;jne	set_cpos
  1973                              <1> 	; 02/02/2022
  1974 000013EC 7405                <1> 	je	short u13
  1975 000013EE E9DE000000          <1> 	jmp	set_cpos
  1976                              <1> u13:
  1977 000013F3 B200                <1> 	mov	dl, 0		; column = 0
  1978                              <1> u10:				; (line feed found)
  1979 000013F5 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1980 000013F8 7228                <1> 	jb 	short u6
  1981                              <1> 	;
  1982                              <1> 	; scroll required
  1983                              <1> u1:	
  1984                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1985 000013FA E8D2000000          <1> 	call	set_cpos
  1986                              <1> 	;
  1987                              <1> 	; determine value to fill with during scroll
  1988                              <1> u2:
  1989                              <1> 	; READ_AC_CURRENT		:
  1990                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1991                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1992                              <1> 	;
  1993                              <1> 	; INPUT				
  1994                              <1> 	;	(AH) = CURRENT CRT MODE
  1995                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1996                              <1> 	;	(DS) = DATA SEGMENT
  1997                              <1> 	;	(ES) = REGEN SEGMENT
  1998                              <1> 	; OUTPUT			
  1999                              <1> 	;	(AL) = CHARACTER READ
  2000                              <1> 	;	(AH) = ATTRIBUTE READ
  2001                              <1> 	;
  2002                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2003                              <1> 	;
  2004                              <1> 	; bl = video page number
  2005                              <1> 	;
  2006 000013FF E82D010000          <1> 	call	find_position	; get regen location and port address
  2007                              <1> 	; dx = status port
  2008                              <1> 	; esi = cursor location/address
  2009                              <1> p11:
  2010 00001404 FB                  <1> 	sti			; enable interrupts
  2011 00001405 90                  <1> 	nop			; allow for small interupts window
  2012 00001406 FA                  <1> 	cli			; blocks interrupts for single loop
  2013 00001407 EC                  <1> 	in	al, dx		; get status from adapter
  2014 00001408 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2015 0000140A 75F8                <1> 	jnz	short p11	; wait until it is
  2016                              <1> p12:				; now wait for either retrace high
  2017 0000140C EC                  <1> 	in	al, dx		; get status
  2018 0000140D A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2019 0000140F 74FB                <1> 	jz	short p12	; wait until either is active	
  2020                              <1> p13:
  2021 00001411 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2022 00001417 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2023                              <1> 	;
  2024                              <1> 	; al = character, ah = attribute
  2025                              <1> 	;
  2026 0000141A FB                  <1> 	sti
  2027                              <1> 	; bl = video page number 	
  2028                              <1> u3:
  2029                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2030                              <1> 	;;sub	cx, cx		; upper left corner
  2031                              <1> 	;;mov	dh, 25-1 	; lower right row
  2032                              <1> 	;;;mov	dl, [CRT_COLS]
  2033                              <1> 	;mov	dl, 80		; lower right column	
  2034                              <1> 	;;dec	dl
  2035                              <1> 	;;mov	dl, 79
  2036                              <1> 
  2037                              <1> 	;;call	scroll_up	; 04/12/2013
  2038                              <1> 	;;; 11/03/2015
  2039                              <1> 	; 02/09/2014
  2040                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2041                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2042                              <1> 	; 11/03/2015
  2043                              <1> 	;sub	cx, cx
  2044                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2045                              <1> 	;
  2046                              <1> 	; 02/02/2022 (simplied scroll up)
  2047                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2048                              <1> 	;
  2049 0000141B B001                <1> 	mov	al, 1		; scroll 1 line up
  2050                              <1> 		; ah = attribute
  2051 0000141D E939010000          <1> 	jmp	scroll_up
  2052                              <1> ;u4:
  2053                              <1> 	;;int	10h		; video-call return
  2054                              <1> 				; scroll up the screen
  2055                              <1> 				; tty return
  2056                              <1> ;u5:
  2057                              <1> 	;retn			; return to the caller
  2058                              <1> 
  2059                              <1> u6:				; set-cursor-inc
  2060 00001422 FEC6                <1> 	inc	dh		; next row
  2061                              <1> 				; set cursor
  2062                              <1> ;u7:					
  2063                              <1> 	;;mov	ah, 02h
  2064                              <1> 	;;jmp	short u4 	; establish the new cursor
  2065                              <1> 	;call	set_cpos
  2066                              <1> 	;jmp 	short u5
  2067 00001424 E9A8000000          <1> 	jmp     set_cpos
  2068                              <1> 
  2069                              <1> 	; check for control characters
  2070                              <1> u8:
  2071 00001429 7434                <1> 	je	short u9
  2072 0000142B 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2073 0000142D 74C6                <1> 	je	short u10
  2074 0000142F 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2075 00001431 7430                <1> 	je	short u11
  2076 00001433 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2077                              <1> 	;jne	short u0
  2078 00001435 7420                <1> 	je	short bs	; 12/12/2013
  2079                              <1> 	; 12/12/2013 (tab stop)
  2080 00001437 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2081 00001439 75A7                <1> 	jne	short u0
  2082 0000143B 88D0                <1> 	mov	al, dl
  2083 0000143D 6698                <1> 	cbw
  2084 0000143F B108                <1> 	mov	cl, 8
  2085 00001441 F6F1                <1> 	div	cl
  2086 00001443 28E1                <1> 	sub	cl, ah
  2087                              <1> ts:
  2088                              <1> 	; 02/09/2014
  2089                              <1> 	; 01/09/2014
  2090 00001445 B020                <1> 	mov	al, 20h
  2091                              <1> tsloop:
  2092                              <1> 	;push	cx
  2093                              <1> 	;push	ax
  2094                              <1> 	; 02/02/2022
  2095 00001447 51                  <1> 	push	ecx
  2096 00001448 50                  <1> 	push	eax
  2097 00001449 30FF                <1> 	xor 	bh, bh
  2098                              <1> 	;mov	bl, [active_page]
  2099 0000144B E881FFFFFF          <1> 	call	m3
  2100                              <1> 	; 02/02/2022
  2101 00001450 58                  <1> 	pop	eax
  2102 00001451 59                  <1>  	pop	ecx
  2103                              <1> 	;pop	ax  ; ah = attribute/color
  2104                              <1> 	;pop	cx
  2105 00001452 FEC9                <1> 	dec	cl
  2106 00001454 75F1                <1> 	jnz	short tsloop
  2107 00001456 C3                  <1> 	retn
  2108                              <1> bs:	
  2109                              <1> 	; back space found
  2110 00001457 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2111                              <1> 	;je	short u7 	; set_cursor
  2112 00001459 7476                <1> 	jz	short set_cpos
  2113                              <1> 	;dec	dx     		; no -- just move it back
  2114                              <1> 	; 02/02/2022
  2115 0000145B FECA                <1> 	dec	dl
  2116                              <1> 	;jmp	short u7
  2117 0000145D EB72                <1> 	jmp	short set_cpos
  2118                              <1> 
  2119                              <1> 	; carriage return found
  2120                              <1> u9:
  2121 0000145F B200                <1> 	mov	dl, 0 		; move to first column
  2122                              <1> 	;jmp	short u7
  2123 00001461 EB6E                <1> 	jmp	short set_cpos
  2124                              <1> 
  2125                              <1> 	; line feed found
  2126                              <1> ;u10:
  2127                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2128                              <1> ;	jne	short u6 	; no, just set the cursor
  2129                              <1> ;       jmp     u1              ; yes, scroll the screen
  2130                              <1> 
  2131                              <1> beeper: 
  2132                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2133                              <1> 	; 18/01/2014
  2134                              <1> 	; 03/12/2013
  2135                              <1> 	; bell found
  2136                              <1> u11:
  2137 00001463 FB                  <1> 	sti
  2138 00001464 3A1D[266B0000]      <1> 	cmp	bl, [active_page]
  2139 0000146A 7551                <1> 	jne	short u12	; Do not sound the beep 
  2140                              <1> 				; if it is not written on the active page
  2141 0000146C 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2142 00001470 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2143                              <1> 	;call	beep		; sound the pod bell
  2144                              <1> 	;jmp	short u5 	; tty_return
  2145                              <1> 	;retn
  2146                              <1> 	
  2147                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2148                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2149                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2150                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2151                              <1> 
  2152                              <1> beep:
  2153                              <1> 	; 07/02/2015
  2154                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2155                              <1> 	; 18/01/2014
  2156                              <1> 	; 03/12/2013
  2157                              <1> 	;
  2158                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2159                              <1> 	;
  2160                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2161                              <1> 	;
  2162                              <1> 	; ENTRY:
  2163                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2164                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2165                              <1> 	; EXIT:			:
  2166                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2167                              <1> 
  2168 00001472 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2169 00001473 FA                  <1> 	cli			; block interrupts during update
  2170 00001474 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2171 00001476 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2172 00001478 EB00                <1> 	jmp	$+2		; I/O delay
  2173 0000147A 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2174 0000147C E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2175 0000147E EB00                <1> 	jmp	$+2		; I/O delay
  2176 00001480 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2177 00001482 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2178 00001484 E461                <1> 	in	al, PORT_B	; get current setting of port
  2179 00001486 88C4                <1> 	mov	ah, al		; save that setting
  2180 00001488 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2181 0000148A E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2182                              <1> 	;popf	; 18/01/2014
  2183 0000148C FB                  <1> 	sti
  2184                              <1> g7:				; 1/64 second per count (bl)
  2185 0000148D B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2186 00001492 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2187 00001497 FECB                <1> 	dec	bl		; (bl) length count expired?
  2188 00001499 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2189                              <1> 	;
  2190                              <1> 	;pushf			; save interrupt status
  2191 0000149B FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2192 0000149C E461                <1> 	in	al, PORT_B	; get current port value
  2193                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2194 0000149E 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2195 000014A0 20C4                <1>         and	ah, al		; someone turned them off during beep
  2196 000014A2 88E0                <1> 	mov	al, ah		; recover value of port
  2197                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2198 000014A4 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2199 000014A6 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2200                              <1> 	;popf			; restore interrupt flag state
  2201 000014A8 FB                  <1> 	sti
  2202 000014A9 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2203 000014AE E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2204                              <1> 	;pushf			; save interrupt status
  2205 000014B3 FA                  <1> 	cli			; block interrupts during update
  2206 000014B4 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2207 000014B6 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2208 000014B8 08E0                <1> 	or	al, ah		; recover value of port_b
  2209 000014BA E661                <1> 	out	PORT_B, al	; restore speaker status
  2210 000014BC 9D                  <1> 	popf			; restore interrupt flag state
  2211                              <1> u12:	
  2212 000014BD C3                  <1> 	retn
  2213                              <1> 
  2214                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2215                              <1> 
  2216                              <1> WAITF:
  2217                              <1> waitf:
  2218                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2219                              <1> 	; 03/12/2013
  2220                              <1> 	;
  2221                              <1> ;	push	ax		; save work register (ah)	
  2222                              <1> ;waitf1:
  2223                              <1> 				; use timer 1 output bits
  2224                              <1> ;	in	al, PORT_B	; read current counter output status
  2225                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2226                              <1> ;	cmp	al, ah		; did it just change
  2227                              <1> ;	je	short waitf1	; wait for a change in output line
  2228                              <1> ;	;
  2229                              <1> ;	mov	ah, al		; save new lflag state
  2230                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2231                              <1> ;	;
  2232                              <1> ;	pop	ax		; restore (ah)
  2233                              <1> ;	retn			; return (cx)=0
  2234                              <1> 
  2235                              <1> ; 02/02/2022
  2236                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2237                              <1> ; 17/12/2014 (dsectrm2.s)
  2238                              <1> ; WAITF
  2239                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2240                              <1> ;
  2241                              <1> ;---WAITF-----------------------------------------------------------------------
  2242                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2243                              <1> ; ENTRY:
  2244                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2245                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2246                              <1> ; EXIT:
  2247                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2248                              <1> ;	(CX) = 0	
  2249                              <1> ;-------------------------------------------------------------------------------
  2250                              <1> 
  2251                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2252                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2253                              <1> 
  2254                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2255 000014BE 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2256                              <1> 	;push	ax
  2257                              <1> 	; 16/12/2014
  2258                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2259 000014BF D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2260                              <1> ;17/12/2014	
  2261                              <1> ;WAITF1:
  2262                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2263                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2264                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2265                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2266                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2267                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2268                              <1> 	;
  2269                              <1> 	; 17/12/2014
  2270                              <1> 	;
  2271                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2272                              <1> 	;
  2273                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2274                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2275                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2276                              <1> WR_STATE_0:
  2277 000014C1 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2278 000014C3 A810                <1> 	TEST	AL,010H
  2279 000014C5 74FA                <1> 	JZ	SHORT WR_STATE_0
  2280                              <1> WR_STATE_1:
  2281 000014C7 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2282 000014C9 A810                <1> 	TEST	AL,010H
  2283 000014CB 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2284 000014CD E2F2                <1>         LOOP    WR_STATE_0
  2285                              <1> 	;
  2286                              <1> 	;pop	ax
  2287 000014CF 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2288 000014D0 C3                  <1> 	RETn				; (CX) = 0
  2289                              <1> 
  2290                              <1> set_cpos:
  2291                              <1> 	; 26/02/2022
  2292                              <1> 	; 02/02/2022
  2293                              <1> 	; 27/06/2015
  2294                              <1> 	; 01/09/2014
  2295                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2296                              <1> 	;
  2297                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2298                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2299                              <1> 	;
  2300                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2301                              <1> 	;
  2302                              <1> 	; SET_CPOS
  2303                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2304                              <1> 	;	NEW X-Y VALUES PASSED
  2305                              <1> 	; INPUT
  2306                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2307                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2308                              <1> 	; OUTPUT
  2309                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2310                              <1> 	;
  2311 000014D1 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2312 000014D4 D0E0                <1>         shl     al, 1   ; word offset
  2313 000014D6 BE[166B0000]        <1> 	mov	esi, cursor_posn
  2314 000014DB 01C6                <1>         add     esi, eax
  2315 000014DD 668916              <1> 	mov	[esi], dx ; save the pointer
  2316 000014E0 381D[266B0000]      <1> 	cmp	[active_page], bl
  2317 000014E6 7536                <1> 	jne	short m17
  2318                              <1> 
  2319 000014E8 FA                  <1> 	cli	; 26/02/2022
  2320                              <1> 
  2321                              <1> 	;call	m18	; CURSOR SET
  2322                              <1> ;m17:			; SET_CPOS_RETURN
  2323                              <1> 	; 01/09/2014
  2324                              <1> ;	retn
  2325                              <1> 		; DX = row/column
  2326                              <1> m18:
  2327 000014E9 E835000000          <1> 	call	position ; determine location in regen buffer	
  2328                              <1> 	;mov	cx, [CRT_START]
  2329                              <1> 	; 26/02/2022
  2330 000014EE 0FB70D[146B0000]    <1> 	movzx	ecx, word [CRT_START]
  2331 000014F5 01C1                <1> 	add	ecx, eax
  2332                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2333                              <1> 			; to the start address (offset) for this page
  2334                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2335                              <1> 	; 26/02/2022
  2336 000014F7 D1E9                <1> 	shr	ecx, 1
  2337 000014F9 B40E                <1> 	mov	ah, 14	; register number for cursor
  2338                              <1> 	
  2339 000014FB E802000000          <1> 	call	m16	; output value to the 6845
  2340 00001500 FB                  <1> 	sti	; 26/02/2022
  2341 00001501 C3                  <1> 	retn
  2342                              <1> 
  2343                              <1> 	; 26/02/2022
  2344                              <1> 	; 02/02/2022
  2345                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2346                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2347                              <1> m16:
  2348                              <1> 	;cli	; 26/02/2022
  2349                              <1> 	;mov	dx, [addr_6845] ; address register
  2350 00001502 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2351 00001506 88E0                <1> 	mov	al, ah	; get value
  2352 00001508 EE                  <1> 	out	dx, al	; register set
  2353                              <1> 	;inc	dx	; data register
  2354                              <1> 	; 02/02/2022
  2355 00001509 FEC2                <1> 	inc	dl
  2356 0000150B EB00                <1> 	jmp	$+2	; i/o delay
  2357 0000150D 88E8                <1> 	mov	al, ch	; data
  2358 0000150F EE                  <1> 	out	dx, al	
  2359                              <1> 	;dec	dx
  2360                              <1> 	; 02/02/2022	
  2361 00001510 FECA                <1> 	dec	dl
  2362 00001512 88E0                <1> 	mov	al, ah
  2363 00001514 FEC0                <1> 	inc	al	; point to other data register
  2364 00001516 EE                  <1> 	out	dx, al	; set for second register
  2365                              <1> 	;inc	dx
  2366                              <1> 	; 02/02/2022
  2367 00001517 FEC2                <1> 	inc	dl
  2368 00001519 EB00                <1> 	jmp	$+2	; i/o delay
  2369 0000151B 88C8                <1> 	mov	al, cl	; second data value
  2370 0000151D EE                  <1> 	out	dx, al
  2371                              <1> 	;sti	; 26/02/2022
  2372                              <1> m17:
  2373 0000151E C3                  <1> 	retn
  2374                              <1> 
  2375                              <1> set_ctype:
  2376                              <1> 	; 07/02/2022
  2377                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2378                              <1> 	;
  2379                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2380                              <1> 
  2381                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2382                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2383                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2384                              <1> ;          OR NO CURSOR AT ALL
  2385                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2386                              <1> 
  2387                              <1> ;------------------------------------------------
  2388                              <1> ; SET_CTYPE
  2389                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2390                              <1> ; INPUT
  2391                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2392                              <1> ; OUTPUT	
  2393                              <1> ;	NONE
  2394                              <1> ;------------------------------------------------
  2395                              <1> 
  2396 0000151F B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2397                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2398                              <1> 	;call	m16	; output cx register
  2399                              <1> 	;retn
  2400                              <1> 	; 07/02/2022
  2401 00001521 EBDF                <1> 	jmp	short m16
  2402                              <1> 
  2403                              <1> position:
  2404                              <1> 	; 26/02/2022
  2405                              <1> 	; 02/02/2022
  2406                              <1> 	; 27/06/2015
  2407                              <1> 	; 02/09/2014
  2408                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2409                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2410                              <1> 	;
  2411                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2412                              <1> 	;
  2413                              <1> 	; POSITION
  2414                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2415                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2416                              <1> 	; INPUT
  2417                              <1> 	;	AX = ROW, COLUMN POSITION
  2418                              <1> 	; OUTPUT
  2419                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2420                              <1> 
  2421                              <1> 		; DX = ROW, COLUMN POSITION
  2422                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2423 00001523 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2424 00001525 B050                <1> 	mov	al, 80	; determine bytes to row	
  2425 00001527 F6E6                <1> 	mul	dh	; row value
  2426                              <1> 	;xor	dh, dh	; 0
  2427                              <1> 	;add	ax, dx	; add column value to the result
  2428                              <1> 	; 26/02/2022
  2429 00001529 00D0                <1> 	add	al, dl
  2430 0000152B 80D400              <1> 	adc	ah, 0	
  2431                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2432                              <1> 	; 02/02/2022
  2433 0000152E D1E0                <1> 	shl	eax, 1
  2434                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2435 00001530 C3                  <1> 	retn
  2436                              <1> 
  2437                              <1> find_position:
  2438                              <1> 	; 02/02/2022
  2439                              <1> 	; 27/06/2015
  2440                              <1> 	; 07/09/2014
  2441                              <1> 	; 02/09/2014
  2442                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2443                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2444 00001531 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2445 00001534 89CE                <1> 	mov	esi, ecx
  2446                              <1> 	;shl	si, 1
  2447                              <1> 	; 02/02/2022
  2448 00001536 D1E6                <1> 	shl	esi, 1
  2449 00001538 668B96[166B0000]    <1> 	mov	dx, [esi+cursor_posn]
  2450 0000153F 7409                <1> 	jz	short p21
  2451                              <1> 	;xor	si, si
  2452                              <1> 	; 02/02/2022
  2453 00001541 31F6                <1> 	xor	esi, esi
  2454                              <1> p20:
  2455                              <1> 	;add	si, [CRT_LEN]
  2456 00001543 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2457 00001548 E2F9                <1> 	loop	p20
  2458                              <1> p21:
  2459 0000154A 6621D2              <1> 	and	dx, dx
  2460 0000154D 7407                <1> 	jz	short p22
  2461 0000154F E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2462 00001554 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2463                              <1> p22:	
  2464                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2465                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2466                              <1> 	;add	dx, 6	; point at status port
  2467 00001556 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2468                              <1> 	; cx = 0
  2469 0000155A C3                  <1> 	retn
  2470                              <1> 
  2471                              <1> scroll_up:
  2472                              <1> 	; 02/02/2022 (simplified scroll up)
  2473                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2474                              <1> 	; 16/01/2016
  2475                              <1> 	; 07/09/2014
  2476                              <1> 	; 02/09/2014
  2477                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2478                              <1> 	; 04/04/2014
  2479                              <1> 	; 04/12/2013
  2480                              <1> 	;
  2481                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2482                              <1> 	;
  2483                              <1> 	; SCROLL UP
  2484                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2485                              <1> 	;	ON THE SCREEN
  2486                              <1> 	; INPUT
  2487                              <1> 	;	(AH) = CURRENT CRT MODE
  2488                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2489                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2490                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2491                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2492                              <1> 	;	(DS) = DATA SEGMENT
  2493                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2494                              <1> 	; OUTPUT
  2495                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2496                              <1> 	;
  2497                              <1> 	;	bh = 0  (02/09/2014)
  2498                              <1> 	;
  2499                              <1> 	; ((ah = 3))
  2500                              <1> 	; cl = left upper column
  2501                              <1> 	; ch = left upper row
  2502                              <1> 	; dl = right lower column
  2503                              <1> 	; dh = right lower row
  2504                              <1> 	;
  2505                              <1> 	; al = line count 
  2506                              <1> 	; ah = attribute to be used on blanked line
  2507                              <1> 	; bl = video page number (0 to 7)
  2508                              <1> 	; 
  2509                              <1> 
  2510                              <1> 	; 02/02/2022 'scroll_up' code
  2511                              <1> 	; ------------------------------------------------------
  2512                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2513                              <1> 
  2514                              <1> 	; INPUT:
  2515                              <1> 	;		
  2516                              <1> 	; al = line count 
  2517                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2518                              <1> 	; ah = attribute to be used on blanked line
  2519                              <1> 	; bl = video page number (0 to 7)
  2520                              <1> 
  2521                              <1> 	;cli
  2522 0000155B 31C9                <1> 	xor	ecx, ecx
  2523 0000155D 88C1                <1> 	mov	cl, al ; line count (cl)
  2524 0000155F BE00800B00          <1> 	mov	esi, 0B8000h
  2525 00001564 3A1D[266B0000]      <1> 	cmp	bl, [active_page]
  2526 0000156A 7411                <1> 	je	short n1
  2527 0000156C 20DB                <1> 	and	bl, bl
  2528 0000156E 7422                <1> 	jz	short n3
  2529 00001570 88DD                <1> 	mov	ch, bl ; video page number
  2530                              <1> n0:
  2531 00001572 6681C6A00F          <1> 	add	si, 25*80*2
  2532 00001577 FECD                <1> 	dec	ch
  2533 00001579 75F7                <1> 	jnz	short n0
  2534 0000157B EB15                <1> 	jmp	short n3
  2535                              <1> n1:
  2536 0000157D 660335[146B0000]    <1> 	add	si, [CRT_START]
  2537                              <1> 	;
  2538 00001584 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2539                              <1> n2:			 ; wait_display_enable
  2540 00001588 EC                  <1> 	in	al, dx	 ; get port
  2541 00001589 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2542 0000158B 74FB                <1> 	jz	short n2 ; wait_display_enable
  2543 0000158D B025                <1> 	mov	al, 25h
  2544 0000158F B2D8                <1> 	mov	dl, 0D8h ; address control port
  2545 00001591 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2546                              <1> n3:
  2547                              <1> 	; cl = line count
  2548                              <1> 	; ah = attribute/color
  2549 00001592 89F7                <1> 	mov	edi, esi
  2550 00001594 20C9                <1> 	and	cl, cl
  2551 00001596 741F                <1> 	jz	short n6
  2552 00001598 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2553 0000159D 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2554 000015A1 F366A5              <1> 	rep	movsw
  2555 000015A4 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2556                              <1> n4:
  2557                              <1> 	; ah = character attribute/cocor
  2558 000015A6 B020                <1> 	mov	al, 20h ; fill with blanks
  2559 000015A8 F366AB              <1> 	rep	stosw
  2560                              <1> 
  2561 000015AB 3A1D[266B0000]      <1> 	cmp	bl, [active_page]
  2562 000015B1 7503                <1> 	jne	short n5
  2563                              <1> 
  2564                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2565 000015B3 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2566                              <1> 	;mov	dx, 03D8h ; always set color card port
  2567 000015B5 EE                  <1> 	out	dx, al
  2568                              <1> n5:
  2569 000015B6 C3                  <1> 	retn
  2570                              <1> n6:
  2571                              <1> 	; clear video page
  2572 000015B7 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2573 000015BB EBE9                <1> 	jmp	short n4
  2574                              <1> 
  2575                              <1> 	; 26/02/2022
  2576                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2577                              <1> 	; ------------------------------------------------------
  2578                              <1> 
  2579                              <1> 	; Test	Line Count
  2580                              <1> 	or	al, al
  2581                              <1> 	jz	short al_set
  2582                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2583                              <1> 	sub	bh, ch
  2584                              <1> 	inc	bh	; adjust difference by 1
  2585                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2586                              <1> 	jne	short al_set ; if not the we're all set
  2587                              <1> 	xor	al, al	; otherwise set al to zero
  2588                              <1> al_set:
  2589                              <1> 	xor	bh, bh	; 0
  2590                              <1> 	;push	ax
  2591                              <1> 	push	eax ; 26/02/2022
  2592                              <1> 	;mov 	esi, [crt_base]
  2593                              <1>         mov     esi, 0B8000h  
  2594                              <1>         cmp     bl, [active_page]
  2595                              <1> 	jne	short n0
  2596                              <1> 	;
  2597                              <1>         mov     ax, [CRT_START]
  2598                              <1>         add     si, ax
  2599                              <1>         jmp     short n1
  2600                              <1> n0:
  2601                              <1>         and     bl, bl
  2602                              <1> 	jz	short n1
  2603                              <1> 	mov	al, bl
  2604                              <1> n0x:
  2605                              <1>         ;add    si, [CRT_LEN]
  2606                              <1>         ;add    esi, 80*25*2 
  2607                              <1>         add     si, 80*25*2
  2608                              <1>         dec	al
  2609                              <1> 	jnz	short n0x
  2610                              <1> n1:	
  2611                              <1>         ; Scroll position
  2612                              <1> 	;push	dx ; 26/02/2022
  2613                              <1> 	mov	dx, cx	; now, upper left position in DX
  2614                              <1> 	call	position
  2615                              <1> 	add	esi, eax
  2616                              <1> 	mov	edi, esi
  2617                              <1> 	;pop	dx	; lower right position in DX
  2618                              <1> 	sub	dx, cx
  2619                              <1> 	inc	dh	; dh = #rows 
  2620                              <1> 	inc	dl	; dl = #cols in block
  2621                              <1> 	;pop	ax	; al = line count, ah = attribute
  2622                              <1> 	pop	eax ; 26/02/2022
  2623                              <1> 	xor	ecx, ecx
  2624                              <1> 	mov	cx, ax
  2625                              <1> 	;mov	ah, [CRT_COLS]
  2626                              <1> 	mov	ah, 80
  2627                              <1> 	mul	ah	; determine offset to from address
  2628                              <1> 	add	ax, ax  ; *2 for attribute byte
  2629                              <1> 	;
  2630                              <1> 	;push	ax	; offset 
  2631                              <1> 	;push	dx
  2632                              <1> 	; 26/02/2022
  2633                              <1> 	push	eax
  2634                              <1> 	push	edx
  2635                              <1> 	;
  2636                              <1> 	; 04/04/2014
  2637                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2638                              <1> n8:                      ; wait_display_enable
  2639                              <1>         in      al, dx   ; get port
  2640                              <1> 	test	al, RVRT ; wait for vertical retrace
  2641                              <1> 	jz	short n8 ; wait_display_enable
  2642                              <1> 	mov	al, 25h
  2643                              <1> 	mov	dl, 0D8h ; address control port
  2644                              <1> 	out	dx, al	; turn off video during vertical retrace
  2645                              <1> 	;pop	dx	; #rows, #cols
  2646                              <1>        	;pop	ax	; offset
  2647                              <1> 	; 26/02/2022
  2648                              <1> 	pop	edx
  2649                              <1> 	pop	eax
  2650                              <1> 	xchg	ax, cx	; 
  2651                              <1> 	; ecx = offset, al = line count, ah = attribute
  2652                              <1> ;n9:
  2653                              <1> 	or	al, al
  2654                              <1>         jz      short n3 
  2655                              <1>         add     esi, ecx ; from address for scroll
  2656                              <1> 	mov	bh, dh  ; #rows in block
  2657                              <1> 	sub	bh, al	; #rows to be moved
  2658                              <1> n2:
  2659                              <1> 	; Move rows
  2660                              <1> 	mov	cl, dl	; get # of cols to move
  2661                              <1> 	push	esi
  2662                              <1> 	push	edi	; save start address
  2663                              <1> n10:
  2664                              <1> 	movsw		; move that line on screen
  2665                              <1> 	dec	cl
  2666                              <1>         jnz     short n10
  2667                              <1> 	pop	edi
  2668                              <1> 	pop	esi	; recover addresses
  2669                              <1>         ;mov    cl, [CRT_COLS] 
  2670                              <1> 	;add	cl, cl
  2671                              <1>         ;mov    ecx, 80*2
  2672                              <1>         mov     cx, 80*2
  2673                              <1>         add     esi, ecx  ; next line
  2674                              <1>         add     edi, ecx
  2675                              <1> 	dec	bh	 ; count of lines to move
  2676                              <1> 	jnz	short n2 ; row loop
  2677                              <1> 	; bh = 0
  2678                              <1> 	mov	dh, al	 ; #rows	
  2679                              <1> n3:
  2680                              <1> 	; attribute in ah
  2681                              <1> 	mov	al, ' '	 ; fill with blanks
  2682                              <1> n3x:
  2683                              <1> 	; Clear rows
  2684                              <1>                 ; dh =  #rows
  2685                              <1>         mov	cl, dl	; get # of cols to clear
  2686                              <1>         push    edi     ; save address
  2687                              <1> n11:
  2688                              <1>         stosw           ; store fill character
  2689                              <1> 	dec	cl
  2690                              <1>         jnz     short n11
  2691                              <1>         pop     edi     ; recover address
  2692                              <1> 	;mov	cl, [CRT_COLS]
  2693                              <1> 	;add	cl, cl
  2694                              <1>         ;mov    ecx, 80*2
  2695                              <1>         mov	cl, 80*2
  2696                              <1>         add     edi, ecx
  2697                              <1> 	dec	dh
  2698                              <1> 	jnz	short n3x ; 16/01/2016
  2699                              <1> 	;
  2700                              <1> 	cmp	bl, [active_page]
  2701                              <1> 	jne	short n6
  2702                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2703                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2704                              <1> 	mov	dx, 03D8h ; always set color card port
  2705                              <1> 	out	dx, al
  2706                              <1> n6:
  2707                              <1> 	retn
  2708                              <1> 
  2709                              <1> %endif
  2710                              <1> 
  2711                              <1> write_c_current:
  2712                              <1> 	; 02/02/2022
  2713                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2714                              <1> 	; 18/01/2014
  2715                              <1> 	; 04/12/2013
  2716                              <1> 	;
  2717                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2718                              <1> 	;
  2719                              <1> 	; WRITE_C_CURRENT
  2720                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2721                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2722                              <1> 	; INPUT	
  2723                              <1> 	;	(AH) = CURRENT CRT MODE
  2724                              <1> 	;	(BH) = DISPLAY PAGE
  2725                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2726                              <1> 	;	(AL) = CHAR TO WRITE
  2727                              <1> 	;	(DS) = DATA SEGMENT
  2728                              <1> 	;	(ES) = REGEN SEGMENT
  2729                              <1> 	; OUTPUT
  2730                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2731                              <1> 
  2732 000015BD FA                  <1> 	cli		
  2733                              <1> 	; bl = video page
  2734                              <1> 	; al = character
  2735                              <1> 	; ah = color/attribute
  2736                              <1> 	;push	dx
  2737                              <1> 	;push	ax	; save character & attribute/color
  2738                              <1> 	; 02/02/2022
  2739 000015BE 52                  <1> 	push	edx
  2740 000015BF 50                  <1> 	push	eax
  2741 000015C0 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2742                              <1> 	; esi = regen location
  2743                              <1> 	; dx = status port
  2744                              <1> 	;
  2745                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2746                              <1> 	;
  2747                              <1> p41:			; wait for horizontal retrace is low or vertical
  2748 000015C5 FB                  <1> 	sti		; enable interrupts first
  2749 000015C6 3A1D[266B0000]      <1>         cmp     bl, [active_page]
  2750 000015CC 7510                <1> 	jne	short p44 
  2751 000015CE FA                  <1> 	cli 		; block interrupts for single loop
  2752 000015CF EC                  <1> 	in	al, dx	; get status from the adapter
  2753 000015D0 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2754 000015D2 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2755 000015D4 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2756 000015D6 75ED                <1> 	jnz	short p41 ; wait until it is
  2757                              <1> p42:			; wait for either retrace high
  2758 000015D8 EC                  <1> 	in	al, dx	; get status again
  2759 000015D9 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2760 000015DB 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2761                              <1> p43:	
  2762 000015DD FB                  <1> 	sti
  2763                              <1> p44:
  2764                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2765                              <1> 	; 02/02/2022
  2766 000015DE 58                  <1> 	pop	eax
  2767 000015DF 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2768                              <1> 			; Retro UNIX 386 v1 feature only!
  2769 000015E5 668906              <1> 	mov	[esi], ax
  2770                              <1> 	;pop	dx
  2771                              <1> 	; 02/02/2022
  2772 000015E8 5A                  <1> 	pop	edx
  2773 000015E9 C3                  <1> 	retn
  2774                              <1> 
  2775                              <1> %if 0	; 02/02/2022
  2776                              <1> 
  2777                              <1> set_mode:
  2778                              <1> 	; 02/02/2022
  2779                              <1> 	; 16/01/2016
  2780                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2781                              <1> 	;
  2782                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2783                              <1> 
  2784                              <1> ;------------------------------------------------------
  2785                              <1> ; SET MODE					      :
  2786                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2787                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2788                              <1> ; INPUT						      :
  2789                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2790                              <1> ; OUTPUT					      :
  2791                              <1> ;	NONE					      :
  2792                              <1> ;------------------------------------------------------
  2793                              <1> 
  2794                              <1> 	push	edi ; 16/01/2016
  2795                              <1> 	push	ebx
  2796                              <1> 	push	edx
  2797                              <1> 	push	ecx ; 16/01/2016
  2798                              <1>         push    eax
  2799                              <1> 
  2800                              <1> 	;mov	dx, 03D4h 	; address or color card
  2801                              <1> 	mov	al, 3
  2802                              <1> ;M8:
  2803                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2804                              <1> 	mov	al, 29h
  2805                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2806                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2807                              <1> 	;push	dx  		; save port value
  2808                              <1> 	;add	dx, 4		; point to control register
  2809                              <1> 	mov	dx, 3D8h
  2810                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2811                              <1> 	;pop	dx
  2812                              <1> ;M9:
  2813                              <1> 	mov	ebx, video_params ; initialization table
  2814                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2815                              <1> 	;xchg 	ah, al
  2816                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2817                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2818                              <1> 	
  2819                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2820                              <1> 	; 02/02/2022
  2821                              <1> 	; dx = 3D8h
  2822                              <1> 	xor	ecx, ecx
  2823                              <1> 	mov	cl, 16
  2824                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2825                              <1> M10:			;  initialization loop
  2826                              <1> 	mov	al, ah 	; get 6845 register number
  2827                              <1> 	out	dx, al
  2828                              <1> 	;inc	dx      ; point to data port
  2829                              <1> 	; 02/02/2022
  2830                              <1> 	inc	dl ; 3D9h
  2831                              <1> 	inc	ah	; next register value
  2832                              <1> 	mov	al, [ebx] ; get table value
  2833                              <1> 	out	dx, al	; out to chip
  2834                              <1> 	inc	ebx	; next in table
  2835                              <1> 	;dec	dx	; back to pointer register
  2836                              <1> 	; 02/02/2022
  2837                              <1> 	dec	dl ; 3D8h
  2838                              <1> 	loop	M10	; do the whole table
  2839                              <1> 	
  2840                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2841                              <1> 	;xor	ax, ax  
  2842                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2843                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2844                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2845                              <1> 	; black background, light gray characeter color, space character
  2846                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2847                              <1> ;M13:			  ; clear buffer
  2848                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2849                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2850                              <1> 
  2851                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2852                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2853                              <1> 			 ; prepare to output to video enable port
  2854                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2855                              <1> 	; 02/02/2022
  2856                              <1> 	;mov	dx, 3D8h
  2857                              <1> 	; 
  2858                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2859                              <1> 	mov	al, 29h
  2860                              <1> 	out	dx, al	 ; set video enable port
  2861                              <1> 
  2862                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2863                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2864                              <1> 	;
  2865                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2866                              <1> 	;
  2867                              <1> ;-----	SET CURSOR POSITIONS
  2868                              <1> 	;push	edi
  2869                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2870                              <1> 	mov	edi, cursor_posn
  2871                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2872                              <1> 	xor	eax, eax
  2873                              <1> 	rep 	stosd	; fill with zeroes
  2874                              <1> 	;pop	edi
  2875                              <1> 
  2876                              <1> ;-----	SET UP OVERSCAN REGISTER
  2877                              <1> 	inc	dx	; set overscan port to a default
  2878                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2879                              <1> ;M14:
  2880                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2881                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2882                              <1> 
  2883                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2884                              <1> 	;
  2885                              <1> 	pop	eax
  2886                              <1> 	pop	ecx ; 16/01/2016
  2887                              <1> 	pop	edx
  2888                              <1> 	pop	ebx
  2889                              <1> 	pop	edi ; 16/01/2016
  2890                              <1> 	retn
  2891                              <1> 
  2892                              <1> %endif
  2893                              <1> 	
  2894                              <1> tty_sw:
  2895                              <1> 	; 02/02/2022
  2896                              <1> 	; 30/06/2015
  2897                              <1> 	; 27/06/2015 
  2898                              <1> 	; 07/09/2014
  2899                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2900                              <1> 	;
  2901                              <1> 	; (Modified registers : EAX)
  2902                              <1> 	;
  2903                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2904                              <1> 	;
  2905                              <1> ;act_disp_page:
  2906                              <1> 	; 30/06/2015
  2907                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2908                              <1> 	; 10/12/2013
  2909                              <1> 	; 04/12/2013
  2910                              <1> 	;
  2911                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2912                              <1> 	;
  2913                              <1> 	; ACT_DISP_PAGE
  2914                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2915                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2916                              <1> 	; INPUT
  2917                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2918                              <1> 	; OUTPUT
  2919                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2920                              <1> 
  2921                              <1> 	;cli
  2922                              <1> 
  2923 000015EA 53                  <1> 	push	ebx
  2924                              <1> 	;push	cx
  2925                              <1> 	;push	dx
  2926                              <1> 	; 02/02/2022
  2927 000015EB 51                  <1> 	push	ecx
  2928 000015EC 52                  <1> 	push	edx
  2929                              <1> 	;
  2930 000015ED A2[266B0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2931                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2932                              <1> 	;mov	cx, 25*80*2
  2933                              <1> 	; 02/02/2022
  2934 000015F2 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2935                              <1> 	; 27/06/2015
  2936 000015F7 0FB6D8              <1> 	movzx	ebx, al
  2937                              <1> 	; 02/02/2022
  2938 000015FA 89D8                <1> 	mov	eax, ebx
  2939                              <1> 	;
  2940                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2941                              <1> 	;mul 	cx	; display page times regen length
  2942                              <1> 	; 02/02/2022
  2943 000015FC F7E1                <1> 	mul	ecx	
  2944                              <1> 	; 10/12/2013
  2945 000015FE 66A3[146B0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2946                              <1> 	;mov	cx, ax	; start address to cx
  2947                              <1> 	; 02/02/2022
  2948 00001604 89C1                <1> 	mov	ecx, eax
  2949                              <1> 	;sar	cx, 1
  2950                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2951                              <1> 	; 02/02/2022
  2952 00001606 D1E9                <1> 	shr	ecx, 1
  2953 00001608 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2954 0000160A E8F3FEFFFF          <1> 	call	m16
  2955                              <1> 	;sal	bx, 1
  2956                              <1> 	; 01/09/2014
  2957 0000160F D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2958 00001611 81C3[166B0000]      <1> 	add	ebx, cursor_posn
  2959 00001617 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2960 0000161A E8CAFEFFFF          <1> 	call	m18
  2961                              <1> 	;
  2962                              <1> 	;pop	dx
  2963                              <1> 	;pop	cx
  2964                              <1> 	; 02/02/2022
  2965 0000161F 5A                  <1> 	pop	edx
  2966 00001620 59                  <1> 	pop	ecx
  2967 00001621 5B                  <1> 	pop	ebx
  2968                              <1> 	;
  2969                              <1> 	;sti
  2970                              <1> 	;
  2971 00001622 C3                  <1> 	retn
  2972                              <1> 
  2973                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2974                              <1> 
  2975                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1868                                  
  1869                                  setup_rtc_int:
  1870                                  ; source: http://wiki.osdev.org/RTC
  1871 00001623 FA                      	cli		; disable interrupts
  1872                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1873                                  	; in order to change this ...
  1874                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1875                                  	; (rate must be above 2 and not over 15)
  1876                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1877 00001624 B08A                    	mov	al, 8Ah 
  1878 00001626 E670                    	out	70h, al ; set index to register A, disable NMI
  1879 00001628 90                      	nop
  1880 00001629 E471                    	in	al, 71h ; get initial value of register A
  1881 0000162B 88C4                    	mov 	ah, al
  1882 0000162D 80E4F0                  	and	ah, 0F0h
  1883 00001630 B08A                    	mov	al, 8Ah 
  1884 00001632 E670                    	out	70h, al ; reset index to register A
  1885 00001634 88E0                    	mov	al, ah
  1886 00001636 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1887 00001638 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1888                                  	; enable RTC interrupt
  1889 0000163A B08B                    	mov	al, 8Bh ;
  1890 0000163C E670                    	out	70h, al ; select register B and disable NMI
  1891 0000163E 90                      	nop
  1892 0000163F E471                    	in	al, 71h ; read the current value of register B
  1893 00001641 88C4                    	mov	ah, al  ;
  1894 00001643 B08B                    	mov 	al, 8Bh ;
  1895 00001645 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1896 00001647 88E0                    	mov	al, ah  ;
  1897 00001649 0C40                    	or	al, 40h ;
  1898 0000164B E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1899 0000164D FB                      	sti
  1900 0000164E C3                      	retn
  1901                                  
  1902                                  ; Write memory information
  1903                                  ; Temporary Code
  1904                                  ; 06/11/2014
  1905                                  ; 14/08/2015 
  1906                                  memory_info:	
  1907 0000164F A1[FC6A0000]            	mov	eax, [memory_size] ; in pages
  1908 00001654 50                      	push	eax
  1909 00001655 C1E00C                  	shl	eax, 12		   ; in bytes
  1910 00001658 BB0A000000              	mov	ebx, 10
  1911 0000165D 89D9                    	mov	ecx, ebx	   ; 10
  1912 0000165F BE[61670000]            	mov	esi, mem_total_b_str	
  1913 00001664 E8AE000000              	call	bintdstr
  1914 00001669 58                      	pop	eax
  1915 0000166A B107                    	mov	cl, 7
  1916 0000166C BE[85670000]            	mov	esi, mem_total_p_str
  1917 00001671 E8A1000000              	call	bintdstr	
  1918                                  	; 14/08/2015
  1919 00001676 E8B9000000              	call	calc_free_mem
  1920                                  	; edx = calculated free pages
  1921                                  	; ecx = 0
  1922 0000167B A1[006B0000]            	mov 	eax, [free_pages]
  1923 00001680 39D0                    	cmp	eax, edx ; calculated free mem value 
  1924                                  		; and initial free mem value are same or not?
  1925 00001682 751D                    	jne 	short pmim ; print mem info with '?' if not
  1926 00001684 52                      	push 	edx ; free memory in pages	
  1927                                  	;mov 	eax, edx
  1928 00001685 C1E00C                  	shl	eax, 12 ; convert page count
  1929                                  			; to byte count
  1930 00001688 B10A                    	mov	cl, 10
  1931 0000168A BE[A5670000]            	mov	esi, free_mem_b_str
  1932 0000168F E883000000              	call	bintdstr
  1933 00001694 58                      	pop	eax
  1934 00001695 B107                    	mov	cl, 7
  1935 00001697 BE[C9670000]            	mov	esi, free_mem_p_str
  1936 0000169C E876000000              	call	bintdstr
  1937                                  pmim:
  1938 000016A1 BE[4F670000]            	mov	esi, msg_memory_info
  1939                                  pmim_nb:	
  1940 000016A6 AC                      	lodsb
  1941 000016A7 08C0                    	or	al, al
  1942 000016A9 740D                    	jz	short pmim_ok
  1943 000016AB 56                      	push	esi
  1944 000016AC 31DB                    	xor	ebx, ebx ; 0
  1945                                  			; Video page 0 (bl=0)
  1946 000016AE B407                    	mov	ah, 07h ; Black background, 
  1947                                  			; light gray forecolor
  1948 000016B0 E812FDFFFF              	call	write_tty
  1949 000016B5 5E                      	pop	esi
  1950 000016B6 EBEE                    	jmp	short pmim_nb
  1951                                  pmim_ok:
  1952 000016B8 C3                      	retn
  1953                                  
  1954                                  ; Convert binary number to hexadecimal string
  1955                                  ; 10/05/2015  
  1956                                  ; dsectpm.s (28/02/2015)
  1957                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1958                                  ; 01/12/2014
  1959                                  ; 25/11/2014
  1960                                  ;
  1961                                  bytetohex:
  1962                                  	; INPUT ->
  1963                                  	; 	AL = byte (binary number)
  1964                                  	; OUTPUT ->
  1965                                  	;	AX = hexadecimal string
  1966                                  	;
  1967 000016B9 53                      	push	ebx
  1968 000016BA 31DB                    	xor	ebx, ebx
  1969 000016BC 88C3                    	mov	bl, al
  1970 000016BE C0EB04                  	shr	bl, 4
  1971 000016C1 8A9B[07170000]          	mov	bl, [ebx+hexchrs]
  1972 000016C7 86D8                    	xchg	bl, al
  1973 000016C9 80E30F                  	and	bl, 0Fh
  1974 000016CC 8AA3[07170000]          	mov	ah, [ebx+hexchrs]
  1975 000016D2 5B                      	pop	ebx	
  1976 000016D3 C3                      	retn
  1977                                  
  1978                                  wordtohex:
  1979                                  	; INPUT ->
  1980                                  	; 	AX = word (binary number)
  1981                                  	; OUTPUT ->
  1982                                  	;	EAX = hexadecimal string
  1983                                  	;
  1984 000016D4 53                      	push	ebx
  1985 000016D5 31DB                    	xor	ebx, ebx
  1986 000016D7 86E0                    	xchg	ah, al
  1987 000016D9 6650                    	push	ax
  1988 000016DB 88E3                    	mov	bl, ah
  1989 000016DD C0EB04                  	shr	bl, 4
  1990 000016E0 8A83[07170000]          	mov	al, [ebx+hexchrs]
  1991 000016E6 88E3                    	mov	bl, ah
  1992 000016E8 80E30F                  	and	bl, 0Fh
  1993 000016EB 8AA3[07170000]          	mov	ah, [ebx+hexchrs]
  1994 000016F1 C1E010                  	shl	eax, 16
  1995 000016F4 6658                    	pop	ax
  1996 000016F6 5B                      	pop	ebx
  1997 000016F7 EBC0                    	jmp	short bytetohex
  1998                                  	;mov	bl, al
  1999                                  	;shr	bl, 4
  2000                                  	;mov	bl, [ebx+hexchrs]
  2001                                  	;xchg	bl, al	 	
  2002                                  	;and	bl, 0Fh
  2003                                  	;mov	ah, [ebx+hexchrs]
  2004                                  	;pop	ebx	
  2005                                  	;retn
  2006                                  
  2007                                  dwordtohex:
  2008                                  	; INPUT ->
  2009                                  	; 	EAX = dword (binary number)
  2010                                  	; OUTPUT ->
  2011                                  	;	EDX:EAX = hexadecimal string
  2012                                  	;
  2013 000016F9 50                      	push	eax
  2014 000016FA C1E810                  	shr	eax, 16
  2015 000016FD E8D2FFFFFF              	call	wordtohex
  2016 00001702 89C2                    	mov	edx, eax
  2017 00001704 58                      	pop	eax
  2018                                  	;call	wordtohex
  2019                                  	;retn
  2020                                  	; 02/01/2022
  2021 00001705 EBCD                    	jmp	short wordtohex
  2022                                  
  2023                                  ; 10/05/2015
  2024                                  hex_digits:
  2025                                  hexchrs:
  2026 00001707 303132333435363738-     	db '0123456789ABCDEF'
  2026 00001710 39414243444546     
  2027                                  
  2028                                  ; Convert binary number to decimal/numeric string
  2029                                  ; 06/11/2014
  2030                                  ; Temporary Code
  2031                                  ;
  2032                                  
  2033                                  bintdstr:
  2034                                  	; EAX = binary number
  2035                                  	; ESI = decimal/numeric string address
  2036                                  	; EBX = divisor (10)
  2037                                  	; ECX = string length (<=10)
  2038 00001717 01CE                    	add	esi, ecx
  2039                                  btdstr0:
  2040 00001719 4E                      	dec	esi
  2041 0000171A 31D2                    	xor	edx, edx
  2042 0000171C F7F3                    	div	ebx
  2043 0000171E 80C230                  	add	dl, 30h
  2044 00001721 8816                    	mov	[esi], dl
  2045 00001723 FEC9                    	dec	cl
  2046 00001725 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2047 00001727 09C0                    	or	eax, eax
  2048 00001729 75EE                    	jnz	short btdstr0
  2049                                  btdstr1:
  2050 0000172B 4E                      	dec	esi
  2051 0000172C C60620                          mov     byte [esi], 20h ; blank space
  2052 0000172F FEC9                    	dec	cl
  2053 00001731 75F8                    	jnz	short btdstr1
  2054                                  btdstr2:
  2055 00001733 C3                      	ret
  2056                                  
  2057                                  ; Calculate free memory pages on M.A.T.
  2058                                  ; 06/11/2014
  2059                                  ; Temporary Code
  2060                                  ;
  2061                                  
  2062                                  calc_free_mem:
  2063 00001734 31D2                    	xor	edx, edx
  2064                                  	;xor	ecx, ecx
  2065                                  	;mov	cx, [mat_size] ; in pages
  2066                                  	; 02/01/2022
  2067 00001736 8B0D[106B0000]          	mov	ecx, [mat_size] ; in pages
  2068 0000173C C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2069 0000173F BE00001000              	mov	esi, MEM_ALLOC_TBL
  2070                                  cfm0:
  2071 00001744 AD                      	lodsd
  2072 00001745 51                      	push	ecx
  2073 00001746 B920000000              	mov	ecx, 32
  2074                                  cfm1:
  2075 0000174B D1E8                    	shr	eax, 1
  2076 0000174D 7301                    	jnc	short cfm2
  2077 0000174F 42                      	inc	edx
  2078                                  cfm2:
  2079 00001750 E2F9                    	loop	cfm1
  2080 00001752 59                      	pop	ecx
  2081 00001753 E2EF                    	loop	cfm0
  2082 00001755 C3                      	ret
  2083                                  
  2084                                  %include 'diskio.inc'  ; 07/03/2015
  2085                              <1> ; Retro UNIX 386 v1.1 Kernel - DISKIO.INC
  2086                              <1> ; Last Modification: 24/12/2021
  2087                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2088                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2089                              <1> 
  2090                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2091                              <1> 
  2092                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2093                              <1> 
  2094                              <1> ; 06/02/2015
  2095                              <1> diskette_io:
  2096 00001756 9C                  <1> 	pushfd
  2097 00001757 0E                  <1> 	push 	cs
  2098 00001758 E809000000          <1> 	call 	DISKETTE_IO_1
  2099 0000175D C3                  <1> 	retn
  2100                              <1> 	
  2101                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2102                              <1> ;//////////////////////////////////////////////////////
  2103                              <1> 
  2104                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2105                              <1> ; 20/02/2015
  2106                              <1> ; 06/02/2015 (unix386.s)
  2107                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2108                              <1> ;
  2109                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2110                              <1> ;
  2111                              <1> ; ADISK.EQU
  2112                              <1> 
  2113                              <1> ;----- Wait control constants 
  2114                              <1> 
  2115                              <1> ;amount of time to wait while RESET is active.
  2116                              <1> 
  2117                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2118                              <1> 					;at 250 KBS xfer rate.
  2119                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2120                              <1> 
  2121                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2122                              <1> 					;status register to become valid
  2123                              <1> 					;before re-reading.
  2124                              <1> 
  2125                              <1> ;After sending a byte to NEC, status register may remain
  2126                              <1> ;incorrectly set for 24 us.
  2127                              <1> 
  2128                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2129                              <1> 					;RQM low.
  2130                              <1> 
  2131                              <1> ; COMMON.MAC
  2132                              <1> ;
  2133                              <1> ;	Timing macros
  2134                              <1> ;
  2135                              <1> 
  2136                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2137                              <1> 		jmp short $+2
  2138                              <1> %endmacro		
  2139                              <1> 
  2140                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2141                              <1> 		jmp short $+2
  2142                              <1> 		jmp short $+2
  2143                              <1> %endmacro
  2144                              <1> 
  2145                              <1> %macro		NEWIODELAY 0
  2146                              <1> 		out	0EBh,al
  2147                              <1> %endmacro 
  2148                              <1> 
  2149                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2150                              <1> ;;; WAIT_FOR_MEM
  2151                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2152                              <1> ;WAIT_FDU_INT_HI	equ	1
  2153                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2154                              <1> ;;; WAIT_FOR_PORT
  2155                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2156                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2157                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2158                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2159                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2160                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2161                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2162                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2163                              <1> ;;; WAIT_REFRESH
  2164                              <1> ;amount of time to wait for head settle, per unit in parameter
  2165                              <1> ;table = 1 ms.
  2166                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2167                              <1> 
  2168                              <1> 
  2169                              <1> ; //////////////// DISKETTE I/O ////////////////
  2170                              <1> 
  2171                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2172                              <1> 
  2173                              <1> ;----------------------------------------
  2174                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2175                              <1> ;----------------------------------------
  2176                              <1> 
  2177                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2178                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2179                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2180                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2181                              <1> 
  2182                              <1> ;----------------------------------------
  2183                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2184                              <1> ;-------------------------------------------------------------------------------
  2185                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2186                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2187                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2188                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2189                              <1> 
  2190                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2191                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2192                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2193                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2194                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2195                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2196                              <1> 
  2197                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2198                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2199                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2200                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2201                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2202                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2203                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2204                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2205                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2206                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2207                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2208                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2209                              <1> 
  2210                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2211                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2212                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2213                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2214                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2215                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2216                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2217                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2218                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2219                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2220                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2221                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2222                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2223                              <1> 
  2224                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2225                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2226                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2227                              <1> 
  2228                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2229                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2230                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2231                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2232                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2233                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2234                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2235                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2236                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2237                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2238                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2239                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2240                              <1> 
  2241                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2242                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2243                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2244                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2245                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2246                              <1> 
  2247                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2248                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2249                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2250                              <1> INTA01		EQU	021H		; 8259 PORT
  2251                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2252                              <1> INTB01		EQU	0A1H		;
  2253                              <1> 
  2254                              <1> ;-------------------------------------------------------------------------------
  2255                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2256                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2257                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2258                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2259                              <1> ;-------------------------------------------------------------------------------
  2260                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2261                              <1> 
  2262                              <1> ;-------------------------------------------------------------------------------
  2263                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2264                              <1> 
  2265                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2266                              <1> ; (unix386.s <-- dsectrm2.s)
  2267                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2268                              <1> 
  2269                              <1> ; 10/12/2014
  2270                              <1> ;
  2271                              <1> ;int40h:
  2272                              <1> ;	pushf
  2273                              <1> ;	push 	cs
  2274                              <1> ;	;cli
  2275                              <1> ;	call 	DISKETTE_IO_1
  2276                              <1> ;	retn
  2277                              <1> 
  2278                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2279                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2280                              <1> ;
  2281                              <1> 
  2282                              <1> ;-- INT13H ---------------------------------------------------------------------
  2283                              <1> ; DISKETTE I/O
  2284                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2285                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2286                              <1> ; INPUT
  2287                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2288                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2289                              <1> ;		ON ALL DRIVES
  2290                              <1> ;------------------------------------------------------------------------------- 
  2291                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2292                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2293                              <1> ;-------------------------------------------------------------------------------
  2294                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2295                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2296                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2297                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2298                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2299                              <1> ;		320/360	320/360	    0-39
  2300                              <1> ;		320/360	1.2M	    0-39
  2301                              <1> ;		1.2M	1.2M	    0-79
  2302                              <1> ;		720K	720K	    0-79
  2303                              <1> ;		1.44M	1.44M	    0-79	
  2304                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2305                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2306                              <1> ;		320/360	320/360	     1-8/9
  2307                              <1> ;		320/360	1.2M	     1-8/9
  2308                              <1> ;		1.2M	1.2M	     1-15
  2309                              <1> ;		720K	720K	     1-9
  2310                              <1> ;		1.44M	1.44M	     1-18		
  2311                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2312                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2313                              <1> ;		320/360	320/360	        8/9
  2314                              <1> ;		320/360	1.2M	        8/9
  2315                              <1> ;		1.2M	1.2M		15
  2316                              <1> ;		720K	720K		9
  2317                              <1> ;		1.44M	1.44M		18
  2318                              <1> ;
  2319                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2320                              <1> ;
  2321                              <1> ;-------------------------------------------------------------------------------
  2322                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2323                              <1> ;-------------------------------------------------------------------------------
  2324                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2325                              <1> ;-------------------------------------------------------------------------------
  2326                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2327                              <1> ;-------------------------------------------------------------------------------
  2328                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2329                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2330                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2331                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2332                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2333                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2334                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2335                              <1> ;		READ/WRITE ACCESS.
  2336                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2337                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2338                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2339                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2340                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2341                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2342                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2343                              <1> ;
  2344                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2345                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2346                              <1> ;		---------------------------------------------
  2347                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2348                              <1> ;		---------------------------------------------
  2349                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2350                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2351                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2352                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2353                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2354                              <1> ;		---------------------------------------------
  2355                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2356                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2357                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2358                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2359                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2360                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2361                              <1> ;-------------------------------------------------------------------------------
  2362                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2363                              <1> ;	REGISTERS
  2364                              <1> ;	  INPUT
  2365                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2366                              <1> ;	  OUTPUT
  2367                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2368                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2369                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2370                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2371                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2372                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2373                              <1> ;	    (BH) - 0
  2374                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2375                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2376                              <1> ;	    (AX) - 0
  2377                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2378                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2379                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2380                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2381                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2382                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2383                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2384                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2385                              <1> ;-------------------------------------------------------------------------------
  2386                              <1> ;	(AH)= 15H  READ DASD TYPE
  2387                              <1> ;	OUTPUT REGISTERS
  2388                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2389                              <1> ;		00 - DRIVE NOT PRESENT	
  2390                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2391                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2392                              <1> ;		03 - RESERVED (FIXED DISK)
  2393                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2394                              <1> ;-------------------------------------------------------------------------------
  2395                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2396                              <1> ;	OUTPUT REGISTERS
  2397                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2398                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2399                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2400                              <1> ;-------------------------------------------------------------------------------
  2401                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2402                              <1> ;	INPUT REGISTERS
  2403                              <1> ;	(AL) -	00 - NOT USED	
  2404                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2405                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2406                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2407                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2408                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2409                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2410                              <1> ;-------------------------------------------------------------------------------
  2411                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2412                              <1> ;	INPUT REGISTERS
  2413                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2414                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2415                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2416                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2417                              <1> ;	OUTPUT REGISTERS:
  2418                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2419                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2420                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2421                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2422                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2423                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2424                              <1> ;-------------------------------------------------------------------------------
  2425                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2426                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2427                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2428                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2429                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2430                              <1> ;		CHANGE ERROR CODE
  2431                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2432                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2433                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2434                              <1> ;
  2435                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2436                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2437                              <1> ;-------------------------------------------------------------------------------
  2438                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2439                              <1> ;	AH = STATUS OF OPERATION
  2440                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2441                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2442                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2443                              <1> ;		TYPE AH=(15)).
  2444                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2445                              <1> ;	FOR READ/WRITE/VERIFY
  2446                              <1> ;		DS,BX,DX,CX PRESERVED
  2447                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2448                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2449                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2450                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2451                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2452                              <1> ;-------------------------------------------------------------------------------
  2453                              <1> ;
  2454                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2455                              <1> ;
  2456                              <1> ;   -----------------------------------------------------------------
  2457                              <1> ;   |       |       |       |       |       |       |       |       |
  2458                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2459                              <1> ;   |       |       |       |       |       |       |       |       |
  2460                              <1> ;   -----------------------------------------------------------------
  2461                              <1> ;	|	|	|	|	|	|	|	|
  2462                              <1> ;	|	|	|	|	|	-----------------
  2463                              <1> ;	|	|	|	|	|		|
  2464                              <1> ;	|	|	|	|    RESERVED		|
  2465                              <1> ;	|	|	|	|		  PRESENT STATE
  2466                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2467                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2468                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2469                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2470                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2471                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2472                              <1> ;	|	|	|	|	110: RESERVED
  2473                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2474                              <1> ;	|	|	|	|
  2475                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2476                              <1> ;	|	|	|
  2477                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2478                              <1> ;	|	|			DRIVE)
  2479                              <1> ;	|	|
  2480                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2481                              <1> ;
  2482                              <1> ;						00: 500 KBS
  2483                              <1> ;						01: 300 KBS
  2484                              <1> ;						10: 250 KBS
  2485                              <1> ;						11: RESERVED
  2486                              <1> ;
  2487                              <1> ;
  2488                              <1> ;-------------------------------------------------------------------------------
  2489                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2490                              <1> ;-------------------------------------------------------------------------------
  2491                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2492                              <1> ;-------------------------------------------------------------------------------
  2493                              <1> 
  2494                              <1> struc MD
  2495 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2496 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2497 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2498 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2499 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2500 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2501 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2502 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2503 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2504 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2505 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2506 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2507 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2508                              <1> endstruc
  2509                              <1> 
  2510                              <1> BIT7OFF	EQU	7FH
  2511                              <1> BIT7ON	EQU	80H
  2512                              <1> 
  2513                              <1> ;;int13h: ; 16/02/2015
  2514                              <1> ;; 16/02/2015 - 21/02/2015
  2515                              <1> int40h:
  2516 0000175E 9C                  <1> 	pushfd
  2517 0000175F 0E                  <1> 	push 	cs
  2518 00001760 E801000000          <1> 	call 	DISKETTE_IO_1
  2519 00001765 C3                  <1> 	retn	
  2520                              <1> 
  2521                              <1> DISKETTE_IO_1:
  2522                              <1> 
  2523 00001766 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2524 00001767 55                  <1> 	PUSH	eBP			; USER REGISTER
  2525 00001768 57                  <1> 	PUSH	eDI			; USER REGISTER
  2526 00001769 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2527 0000176A 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2528 0000176B 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2529 0000176C 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2530                              <1> 					; [BP]   = SECTOR #
  2531                              <1> 					; [BP+1] = TRACK #
  2532                              <1> 					; [BP+2] = BUFFER OFFSET
  2533                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2534                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2535                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2536                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2537                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2538                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2539                              <1> 					; BH/[BP+3] = 0
  2540                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2541                              <1> 					; DH/[BP+5] = MAX HEAD #
  2542                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2543 0000176E 06                  <1> 	push	es ; 06/02/2015	
  2544 0000176F 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2545 00001770 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2546                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2547                              <1> 	;mov	cx, cs
  2548                              <1> 	;mov	ds, cx
  2549 00001771 66B91000            <1> 	mov	cx, KDATA
  2550 00001775 8ED9                <1>         mov     ds, cx
  2551 00001777 8EC1                <1>         mov     es, cx
  2552                              <1> 
  2553                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2554 00001779 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2555 0000177C 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2556 0000177E B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2557                              <1> OK_FUNC:
  2558 00001780 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2559 00001783 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2560 00001785 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2561 00001788 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2562 0000178A 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2563 0000178D 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2564 0000178F B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2565                              <1> OK_DRV:
  2566 00001791 31C9                <1> 	xor	ecx, ecx
  2567                              <1> 	;mov	esi, ecx ; 08/02/2015
  2568                              <1> 	; 24/12/2021
  2569 00001793 89CE                <1> 	mov	esi, ecx
  2570 00001795 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2571 00001797 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2572                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2573                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2574 00001799 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2575 0000179C BB[D4170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2576 000017A1 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2577 000017A3 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2578 000017A5 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2579 000017A7 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2580 000017AA 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2581                              <1> 	;
  2582                              <1> 	; 11/12/2014
  2583 000017AD 8815[E1650000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2584                              <1> 	;
  2585 000017B3 8A25[7C6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2586 000017B9 C605[7C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2587                              <1> 
  2588                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2589                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2590                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2591                              <1> ;
  2592                              <1> ;		DI	: DRIVE #
  2593                              <1> ;		SI-HI	: HEAD #
  2594                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2595                              <1> ;		ES	: BUFFER SEGMENT
  2596                              <1> ;		[BP]	: SECTOR #
  2597                              <1> ;		[BP+1]	: TRACK #
  2598                              <1> ;		[BP+2]	: BUFFER OFFSET
  2599                              <1> ;
  2600                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2601                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2602                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2603                              <1> ;	SPECIFIC ERROR CODE.
  2604                              <1> ;
  2605                              <1> 					; (AH) = @DSKETTE_STATUS
  2606 000017C0 FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2607 000017C2 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2608 000017C3 1F                  <1> 	POP	DS
  2609 000017C4 07                  <1> 	pop	es	; 06/02/2015
  2610 000017C5 59                  <1> 	POP	eCX
  2611 000017C6 5B                  <1> 	POP	eBX
  2612 000017C7 5A                  <1> 	POP	eDX
  2613 000017C8 5F                  <1> 	POP	eDI
  2614 000017C9 89E5                <1> 	MOV	eBP, eSP
  2615 000017CB 50                  <1> 	PUSH	eAX
  2616 000017CC 9C                  <1> 	PUSHFd
  2617 000017CD 58                  <1> 	POP	eAX
  2618                              <1> 	;MOV	[BP+6], AX
  2619 000017CE 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2620 000017D1 58                  <1> 	POP	eAX
  2621 000017D2 5D                  <1> 	POP	eBP
  2622 000017D3 CF                  <1> 	IRETd
  2623                              <1> 
  2624                              <1> ;-------------------------------------------------------------------------------
  2625                              <1> ; DW --> dd (06/02/2015)
  2626 000017D4 [38180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2627 000017D8 [AD180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2628 000017DC [BD180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2629 000017E0 [CE180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2630 000017E4 [DF180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2631 000017E8 [F0180000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2632 000017EC [74190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2633 000017F0 [74190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2634 000017F4 [80190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2635 000017F8 [74190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2636 000017FC [74190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2637 00001800 [74190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2638 00001804 [74190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2639 00001808 [74190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2640 0000180C [74190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2641 00001810 [74190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2642 00001814 [74190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2643 00001818 [74190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2644 0000181C [74190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2645 00001820 [74190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2646 00001824 [74190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2647 00001828 [3F1A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2648 0000182C [671A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2649 00001830 [A01A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2650 00001834 [211B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2651                              <1> FNC_TAE EQU     $                       ; END
  2652                              <1> 
  2653                              <1> ;-------------------------------------------------------------------------------
  2654                              <1> ; DISK_RESET	(AH = 00H)	
  2655                              <1> ;		RESET THE DISKETTE SYSTEM.
  2656                              <1> ;
  2657                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2658                              <1> ;-------------------------------------------------------------------------------
  2659                              <1> DSK_RESET:
  2660 00001838 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2661 0000183C FA                  <1> 	CLI				; NO INTERRUPTS
  2662 0000183D A0[7A6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2663 00001842 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2664 00001844 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2665                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2666 00001847 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2667 00001849 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2668 0000184A C605[796B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2669                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2670                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2671                              <1> 					;      PULSE WIDTH)
  2672                              <1> 	; 19/12/2014
  2673                              <1> 	NEWIODELAY
  2146 00001851 E6EB                <2>  out 0EBh,al
  2674                              <1> 
  2675                              <1> 	; 17/12/2014 
  2676                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2677 00001853 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2678                              <1> wdw1:
  2679                              <1> 	NEWIODELAY   ; 27/02/2015
  2146 00001858 E6EB                <2>  out 0EBh,al
  2680 0000185A E2FC                <1> 	loop	wdw1
  2681                              <1> 	;
  2682 0000185C 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2683 0000185E EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2684                              <1> 	; 16/12/2014
  2685                              <1> 	IODELAY
  2141 0000185F EB00                <2>  jmp short $+2
  2142 00001861 EB00                <2>  jmp short $+2
  2686                              <1> 	;
  2687                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2688 00001863 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2689 00001868 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2690 0000186A 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2691                              <1> NXT_DRV:
  2692                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2693                              <1> 	; 24/12/2021
  2694 0000186E 51                  <1> 	push	ecx
  2695 0000186F B8[A3180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2696 00001874 50                  <1> 	PUSH	eAX			; "
  2697 00001875 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2698 00001877 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2699 0000187C 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2700 0000187D E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2701                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2702                              <1> 	; 24/12/2021
  2703 00001882 59                  <1> 	pop	ecx
  2704 00001883 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2705 00001885 3A0D[7D6B0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2706 0000188B 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2707 0000188D FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2708 0000188F 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2709 00001892 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2710                              <1> 	;
  2711 00001894 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2712                              <1> RESBAC:
  2713 00001899 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2714                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2715                              <1> 	; 24/12/2021
  2716 0000189E 89F3                <1> 	mov	ebx, esi
  2717 000018A0 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2718 000018A2 C3                  <1> 	RETn		
  2719                              <1> DR_POP_ERR:
  2720                              <1> 	;POP	CX			; CLEAR STACK
  2721                              <1> 	; 24/12/2021
  2722 000018A3 59                  <1> 	pop	ecx
  2723                              <1> DR_ERR:
  2724 000018A4 800D[7C6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2725 000018AB EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2726                              <1> 
  2727                              <1> ;-------------------------------------------------------------------------------
  2728                              <1> ; DISK_STATUS	(AH = 01H)
  2729                              <1> ;	DISKETTE STATUS.
  2730                              <1> ;
  2731                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2732                              <1> ;
  2733                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2734                              <1> ;-------------------------------------------------------------------------------
  2735                              <1> DSK_STATUS:
  2736 000018AD 8825[7C6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2737 000018B3 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2738                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2739                              <1> 	; 24/12/2021
  2740 000018B8 89F3                <1> 	mov	ebx, esi
  2741 000018BA 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2742 000018BC C3                  <1> 	RETn		
  2743                              <1> 
  2744                              <1> ;-------------------------------------------------------------------------------
  2745                              <1> ; DISK_READ	(AH = 02H)	
  2746                              <1> ;	DISKETTE READ.
  2747                              <1> ;
  2748                              <1> ; ON ENTRY:	DI	: DRIVE #
  2749                              <1> ;		SI-HI	: HEAD #
  2750                              <1> ;		SI-LOW	: # OF SECTORS
  2751                              <1> ;		ES	: BUFFER SEGMENT
  2752                              <1> ;		[BP]	: SECTOR #
  2753                              <1> ;		[BP+1]	: TRACK #
  2754                              <1> ;		[BP+2]	: BUFFER OFFSET
  2755                              <1> ;
  2756                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2757                              <1> ;-------------------------------------------------------------------------------
  2758                              <1> 
  2759                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2760                              <1> 
  2761                              <1> DSK_READ:
  2762 000018BD 8025[7A6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2763 000018C4 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2764 000018C8 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2765 000018CD C3                  <1> 	RETn
  2766                              <1> 
  2767                              <1> ;-------------------------------------------------------------------------------
  2768                              <1> ; DISK_WRITE	(AH = 03H)
  2769                              <1> ;	DISKETTE WRITE.
  2770                              <1> ;
  2771                              <1> ; ON ENTRY:	DI	: DRIVE #
  2772                              <1> ;		SI-HI	: HEAD #
  2773                              <1> ;		SI-LOW	: # OF SECTORS
  2774                              <1> ;		ES	: BUFFER SEGMENT
  2775                              <1> ;		[BP]	: SECTOR #
  2776                              <1> ;		[BP+1]	: TRACK #
  2777                              <1> ;		[BP+2]	: BUFFER OFFSET
  2778                              <1> ;
  2779                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2780                              <1> ;-------------------------------------------------------------------------------
  2781                              <1> 
  2782                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2783                              <1> 
  2784                              <1> DSK_WRITE:
  2785 000018CE 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2786 000018D2 800D[7A6B0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2787 000018D9 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2788 000018DE C3                  <1> 	RETn
  2789                              <1> 
  2790                              <1> ;-------------------------------------------------------------------------------
  2791                              <1> ; DISK_VERF	(AH = 04H)
  2792                              <1> ;	DISKETTE VERIFY.
  2793                              <1> ;
  2794                              <1> ; ON ENTRY:	DI	: DRIVE #
  2795                              <1> ;		SI-HI	: HEAD #
  2796                              <1> ;		SI-LOW	: # OF SECTORS
  2797                              <1> ;		ES	: BUFFER SEGMENT
  2798                              <1> ;		[BP]	: SECTOR #
  2799                              <1> ;		[BP+1]	: TRACK #
  2800                              <1> ;		[BP+2]	: BUFFER OFFSET
  2801                              <1> ;
  2802                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2803                              <1> ;-------------------------------------------------------------------------------
  2804                              <1> DSK_VERF:
  2805 000018DF 8025[7A6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2806 000018E6 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2807 000018EA E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2808 000018EF C3                  <1> 	RETn
  2809                              <1> 
  2810                              <1> ;-------------------------------------------------------------------------------
  2811                              <1> ; DISK_FORMAT	(AH = 05H)
  2812                              <1> ;	DISKETTE FORMAT.
  2813                              <1> ;
  2814                              <1> ; ON ENTRY:	DI	: DRIVE #
  2815                              <1> ;		SI-HI	: HEAD #
  2816                              <1> ;		SI-LOW	: # OF SECTORS
  2817                              <1> ;		ES	: BUFFER SEGMENT
  2818                              <1> ;		[BP]	: SECTOR #
  2819                              <1> ;		[BP+1]	: TRACK #
  2820                              <1> ;		[BP+2]	: BUFFER OFFSET
  2821                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2822                              <1> ;
  2823                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2824                              <1> ;-------------------------------------------------------------------------------
  2825                              <1> DSK_FORMAT:
  2826 000018F0 E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2827 000018F5 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2828 000018FA 800D[7A6B0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2829 00001901 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2830 00001906 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2831 00001908 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2832 0000190D E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2833 00001912 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2834 00001914 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2835                              <1> FM_WR:
  2836 00001919 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2837 0000191E 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2838 00001920 B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2839 00001922 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2840 00001927 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2841 00001929 B8[65190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2842 0000192E 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2843 0000192F B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2844 00001931 E80E090000          <1> 	CALL	GET_PARM
  2845 00001936 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2846 0000193B B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2847 0000193D E802090000          <1> 	CALL	GET_PARM
  2848 00001942 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2849 00001947 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2850 00001949 E8F6080000          <1> 	CALL	GET_PARM
  2851 0000194E E8F7090000          <1> 	CALL	NEC_OUTPUT
  2852 00001953 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2853 00001955 E8EA080000          <1> 	CALL	GET_PARM
  2854 0000195A E8EB090000          <1> 	CALL	NEC_OUTPUT
  2855 0000195F 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2856 00001960 E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2857                              <1> FM_DON:
  2858 00001965 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2859 0000196A E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2860                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2861 0000196F 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2862 00001971 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2863 00001973 C3                  <1> 	RETn
  2864                              <1> 
  2865                              <1> ;-------------------------------------------------------------------------------
  2866                              <1> ; FNC_ERR
  2867                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2868                              <1> ;	SET BAD COMMAND IN STATUS.
  2869                              <1> ;
  2870                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2871                              <1> ;-------------------------------------------------------------------------------
  2872                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2873                              <1> 	;MOV	AX,SI			; RESTORE AL
  2874                              <1> 	; 24/12/2021
  2875 00001974 89F0                <1> 	mov	eax, esi
  2876 00001976 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2877 00001978 8825[7C6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2878 0000197E F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2879 0000197F C3                  <1> 	RETn
  2880                              <1> 
  2881                              <1> ;-------------------------------------------------------------------------------
  2882                              <1> ; DISK_PARMS	(AH = 08H)	
  2883                              <1> ;	READ DRIVE PARAMETERS.
  2884                              <1> ;
  2885                              <1> ; ON ENTRY:	DI : DRIVE #
  2886                              <1> ;
  2887                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2888                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2889                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2890                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2891                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2892                              <1> ;		BH/[BP+3] = 0
  2893                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2894                              <1> ;		DH/[BP+5] = MAX HEAD #
  2895                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2896                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2897                              <1> ;		AX        = 0
  2898                              <1> ;
  2899                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2900                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2901                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2902                              <1> ;		       CALLER.
  2903                              <1> ;-------------------------------------------------------------------------------
  2904                              <1> DSK_PARMS:
  2905 00001980 E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2906                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2907 00001985 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2908 00001987 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2909                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2910                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2911                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2912                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2913                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2914                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2915                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2916                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2917                              <1> 	;sub	edx, edx
  2918 0000198A 66A1[EE650000]      <1> 	mov     ax, [fd0_type]
  2919 00001990 6621C0              <1> 	and     ax, ax
  2920 00001993 7473                <1> 	jz      short NON_DRV
  2921 00001995 FEC2                <1> 	inc     dl
  2922 00001997 20E4                <1> 	and     ah, ah
  2923 00001999 7402                <1> 	jz      short STO_DL
  2924 0000199B FEC2                <1> 	inc     dl
  2925                              <1> STO_DL:
  2926                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2927 0000199D 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2928 000019A0 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2929 000019A4 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2930                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2931 000019A6 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2932 000019AA E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2933                              <1> 	;;20/02/2015
  2934                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2935                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2936 000019AF 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2937 000019B1 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2938 000019B6 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2939                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2940 000019B8 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2941 000019BB 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2942 000019BE 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2943 000019C1 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2944                              <1> CHK_EST:
  2945 000019C3 8AA7[896B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2946 000019C9 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2947 000019CC 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2948                              <1> USE_EST:
  2949 000019CE 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2950 000019D1 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2951 000019D4 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2952                              <1> 
  2953                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2954                              <1> 
  2955 000019D6 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2956 000019D8 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2957 000019DD 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2958 000019E0 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2959 000019E3 F687[896B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2960 000019EA 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2961                              <1> 
  2962                              <1> ;-----	IT IS 1.44 MB DRIVE
  2963                              <1> 
  2964                              <1> PARM144:
  2965 000019EC B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2966 000019EE E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2967 000019F3 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2968 000019F6 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2969                              <1> STO_CX:
  2970 000019F9 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2971                              <1> ES_DI:
  2972                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2973 000019FC 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2974                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2975                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2976                              <1> DP_OUT:
  2977 000019FF E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2978                              <1> 	;XOR	AX,AX			; CLEAR
  2979                              <1> 	; 24/12/2021
  2980 00001A04 31C0                <1> 	xor	eax, eax
  2981 00001A06 F8                  <1> 	CLC
  2982 00001A07 C3                  <1> 	RETn
  2983                              <1> 
  2984                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2985                              <1> 
  2986                              <1> NON_DRV:
  2987                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2988 00001A08 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2989                              <1> NON_DRV1:
  2990 00001A0B 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2991 00001A10 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2992                              <1> 
  2993                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2994                              <1> 	
  2995 00001A12 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2996                              <1> 	;MOV	AX,SI			; RESTORE AL
  2997 00001A17 89F0                <1> 	mov	eax, esi ; 24/12/2021
  2998 00001A19 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2999 00001A1B F9                  <1> 	STC
  3000 00001A1C C3                  <1> 	RETn
  3001                              <1> 
  3002                              <1> NON_DRV2:
  3003                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  3004 00001A1D 31C0                <1> 	xor	eax, eax	
  3005 00001A1F 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  3006                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  3007 00001A23 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  3008                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  3009 00001A26 89450C              <1> 	mov	[ebp+12], eax
  3010                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  3011 00001A29 EBD4                <1> 	JMP	SHORT DP_OUT
  3012                              <1> 
  3013                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  3014                              <1> 
  3015                              <1> USE_EST2:
  3016 00001A2B B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  3017 00001A2D E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3018 00001A32 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3019 00001A35 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  3020 00001A38 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3021 00001A3B 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  3022 00001A3D EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  3023                              <1> 
  3024                              <1> ;-------------------------------------------------------------------------------
  3025                              <1> ; DISK_TYPE (AH = 15H)	
  3026                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  3027                              <1> ;
  3028                              <1> ;  ON ENTRY:	DI = DRIVE #
  3029                              <1> ;
  3030                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  3031                              <1> ;-------------------------------------------------------------------------------
  3032                              <1> DSK_TYPE:
  3033 00001A3F E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3034 00001A44 8A87[896B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  3035 00001A4A 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  3036 00001A4C 7415                <1> 	JZ	short NO_DRV
  3037 00001A4E B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3038 00001A50 A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3039 00001A52 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3040 00001A54 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3041                              <1> DT_BACK:
  3042                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3043 00001A56 50                  <1> 	push	eax ; 24/12/2021
  3044 00001A57 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3045                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3046 00001A5C 58                  <1> 	pop	eax ; 24/12/2021
  3047 00001A5D F8                  <1> 	CLC				; NO ERROR
  3048                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3049                              <1> 	; 24/12/2021
  3050 00001A5E 89F3                <1> 	mov	ebx, esi
  3051 00001A60 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3052 00001A62 C3                  <1> 	RETn
  3053                              <1> NO_DRV:	
  3054 00001A63 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3055 00001A65 EBEF                <1> 	JMP	SHORT DT_BACK
  3056                              <1> 
  3057                              <1> ;-------------------------------------------------------------------------------
  3058                              <1> ; DISK_CHANGE	(AH = 16H)
  3059                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3060                              <1> ;
  3061                              <1> ; ON ENTRY:	DI = DRIVE #
  3062                              <1> ;
  3063                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3064                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3065                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3066                              <1> ;-------------------------------------------------------------------------------
  3067                              <1> DSK_CHANGE:
  3068 00001A67 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3069 00001A6C 8A87[896B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3070 00001A72 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3071 00001A74 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3072 00001A76 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3073 00001A78 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3074                              <1> DC0:
  3075 00001A7A E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3076 00001A7F 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3077                              <1> 
  3078 00001A81 C605[7C6B0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3079                              <1> 
  3080 00001A88 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3081 00001A8D E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3082                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3083                              <1> 	; 24/12/2021
  3084 00001A92 89F3                <1> 	mov	ebx, esi
  3085 00001A94 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3086 00001A96 C3                  <1> 	RETn
  3087                              <1> DC_NON:
  3088 00001A97 800D[7C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3089 00001A9E EBE8                <1> 	JMP	SHORT FINIS
  3090                              <1> 
  3091                              <1> ;-------------------------------------------------------------------------------
  3092                              <1> ; FORMAT_SET	(AH = 17H)
  3093                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3094                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3095                              <1> ;
  3096                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3097                              <1> ;		DI     = DRIVE #
  3098                              <1> ;
  3099                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3100                              <1> ;		AH = @DSKETTE_STATUS
  3101                              <1> ;		CY = 1 IF ERROR
  3102                              <1> ;-------------------------------------------------------------------------------
  3103                              <1> FORMAT_SET:
  3104 00001AA0 E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3105                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3106                              <1> 	; 24/12/2021
  3107 00001AA5 56                  <1> 	push	esi
  3108 00001AA6 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3109 00001AA9 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3110 00001AAB 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3111 00001AAE 80A7[896B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3112 00001AB5 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3113 00001AB7 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3114 00001AB9 808F[896B0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3115 00001AC0 EB48                <1> 	JMP	SHORT S0
  3116                              <1> NOT_320:
  3117 00001AC2 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3118 00001AC7 803D[7C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3119 00001ACE 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3120                              <1> S3:
  3121 00001AD0 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3122 00001AD2 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3123 00001AD4 808F[896B0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3124 00001ADB EB2D                <1> 	JMP	SHORT S0
  3125                              <1> NOT_320_12:
  3126 00001ADD 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3127 00001ADF 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3128 00001AE1 808F[896B0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3129 00001AE8 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3130                              <1> NOT_12:	
  3131 00001AEA 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3132 00001AEC 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3133                              <1> 
  3134 00001AEE F687[896B0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3135 00001AF5 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3136 00001AF7 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3137 00001AF9 F687[896B0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3138 00001B00 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3139                              <1> ASSUME:
  3140 00001B02 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3141                              <1> OR_IT_IN:
  3142 00001B04 0887[896B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3143                              <1> S0:
  3144 00001B0A E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3145 00001B0F E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3146                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3147                              <1> 	; 24/12/2021
  3148 00001B14 5B                  <1> 	pop	ebx
  3149 00001B15 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3150 00001B17 C3                  <1> 	RETn
  3151                              <1> FS_ERR:
  3152 00001B18 C605[7C6B0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3153 00001B1F EBE9                <1> 	JMP	SHORT S0
  3154                              <1> 
  3155                              <1> ;-------------------------------------------------------------------------------
  3156                              <1> ; SET_MEDIA	(AH = 18H)
  3157                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3158                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3159                              <1> ;
  3160                              <1> ; ON ENTRY:
  3161                              <1> ;	[BP]	= SECTOR PER TRACK
  3162                              <1> ;	[BP+1]	= TRACK #
  3163                              <1> ;	DI	= DRIVE #
  3164                              <1> ;
  3165                              <1> ; ON EXIT:
  3166                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3167                              <1> ;	IF NO ERROR:
  3168                              <1> ;		AH = 0
  3169                              <1> ;		CY = 0
  3170                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3171                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3172                              <1> ;	IF ERROR:	
  3173                              <1> ;		AH = @DSKETTE_STATUS
  3174                              <1> ;		CY = 1
  3175                              <1> ;-------------------------------------------------------------------------------
  3176                              <1> SET_MEDIA:
  3177 00001B21 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3178 00001B26 F687[896B0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3179 00001B2D 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3180 00001B2F E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3181 00001B34 803D[7C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3182 00001B3B 746B                <1> 	JE	short SM_RTN
  3183 00001B3D C605[7C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3184                              <1> SM_CMOS:
  3185 00001B44 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3186                              <1> 	;;20/02/2015
  3187                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3188                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3189 00001B49 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3190 00001B4B E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3191 00001B50 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3192 00001B52 57                  <1> 	PUSH	eDI			; SAVE REG.
  3193 00001B53 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3194 00001B55 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3195                              <1> DR_SEARCH:
  3196 00001B5A 8AA3[6C650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3197 00001B60 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3198 00001B63 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3199 00001B65 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3200                              <1> DR_FND:
  3201 00001B67 8BBB[6D650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3202                              <1> MD_SEARCH:
  3203 00001B6D 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3204 00001B70 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3205 00001B73 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3206 00001B75 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3207 00001B78 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3208 00001B7B 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3209                              <1> NXT_MD:
  3210                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3211 00001B7D 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3212 00001B80 E2D8                <1> 	LOOP    DR_SEARCH
  3213 00001B82 5F                  <1> 	POP	eDI			; RESTORE REG.
  3214                              <1> MD_NOT_FND:
  3215 00001B83 C605[7C6B0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3216 00001B8A EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3217                              <1> MD_FND:
  3218 00001B8C 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3219 00001B8F 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3220 00001B91 7502                <1> 	JNE	short MD_SET
  3221 00001B93 0C20                <1> 	OR	AL,DBL_STEP
  3222                              <1> MD_SET:
  3223                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3224 00001B95 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3225 00001B98 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3226 00001B9A 5F                  <1> 	POP	eDI
  3227 00001B9B 80A7[896B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3228 00001BA2 0887[896B0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3229                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3230                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3231                              <1> SM_RTN:
  3232 00001BA8 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3233 00001BAD E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3234 00001BB2 C3                  <1> 	RETn
  3235                              <1> 
  3236                              <1> ;----------------------------------------------------------------
  3237                              <1> ; DR_TYPE_CHECK							:
  3238                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3239                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3240                              <1> ; ON ENTRY:							:
  3241                              <1> ;	AL = DRIVE TYPE						:
  3242                              <1> ; ON EXIT:							:
  3243                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3244                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3245                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3246                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3247                              <1> ; REGISTERS ALTERED: eBX						:
  3248                              <1> ;----------------------------------------------------------------		
  3249                              <1> DR_TYPE_CHECK:
  3250                              <1> 	;PUSH	AX			
  3251                              <1> 	; 24/12/2021
  3252 00001BB3 50                  <1> 	push	eax
  3253 00001BB4 51                  <1> 	PUSH	eCX
  3254 00001BB5 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3255 00001BB7 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3256                              <1> TYPE_CHK:	
  3257 00001BBC 8AA3[6C650000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3258 00001BC2 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3259 00001BC4 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3260                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3261 00001BC6 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3262 00001BC9 E2F1                <1> 	LOOP    TYPE_CHK
  3263                              <1> 	;
  3264 00001BCB BB[CB650000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3265                              <1> 					; Default for GET_PARM (11/12/2014)
  3266                              <1> 	;
  3267 00001BD0 F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3268 00001BD1 EB06                <1> 	JMP	SHORT TYPE_RTN
  3269                              <1> DR_TYPE_VALID:
  3270 00001BD3 8B9B[6D650000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3271                              <1> TYPE_RTN:
  3272 00001BD9 59                  <1> 	POP	eCX
  3273                              <1> 	;POP	AX
  3274                              <1> 	; 24/12/2021
  3275 00001BDA 58                  <1> 	pop	eax
  3276 00001BDB C3                  <1> 	RETn	
  3277                              <1> 		
  3278                              <1> ;----------------------------------------------------------------
  3279                              <1> ; SEND_SPEC							:
  3280                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3281                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3282                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3283                              <1> ; ON EXIT:	NONE						:	
  3284                              <1> ; REGISTERS ALTERED: CX, DX					:
  3285                              <1> ;----------------------------------------------------------------		
  3286                              <1> SEND_SPEC:
  3287 00001BDC 50                  <1> 	PUSH	eAX			; SAVE AX
  3288 00001BDD B8[031C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3289 00001BE2 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3290 00001BE3 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3291 00001BE5 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3292 00001BEA 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3293 00001BEC E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3294 00001BF1 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3295 00001BF6 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3296 00001BF8 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3297 00001BFD E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3298 00001C02 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3299                              <1> SPECBAC:
  3300 00001C03 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3301 00001C04 C3                  <1> 	RETn
  3302                              <1> 
  3303                              <1> ;----------------------------------------------------------------
  3304                              <1> ; SEND_SPEC_MD							:
  3305                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3306                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3307                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3308                              <1> ; ON EXIT:	NONE						:	
  3309                              <1> ; REGISTERS ALTERED: AX						:
  3310                              <1> ;----------------------------------------------------------------		
  3311                              <1> SEND_SPEC_MD:
  3312 00001C05 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3313 00001C06 B8[231C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3314 00001C0B 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3315 00001C0C B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3316 00001C0E E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3317 00001C13 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3318 00001C15 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3319 00001C1A 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3320 00001C1D E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3321 00001C22 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3322                              <1> SPEC_ESBAC:
  3323 00001C23 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3324 00001C24 C3                  <1> 	RETn
  3325                              <1> 
  3326                              <1> ;-------------------------------------------------------------------------------
  3327                              <1> ; XLAT_NEW  
  3328                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3329                              <1> ;	MODE TO NEW ARCHITECTURE.
  3330                              <1> ;
  3331                              <1> ; ON ENTRY:	DI = DRIVE #
  3332                              <1> ;-------------------------------------------------------------------------------
  3333                              <1> XLAT_NEW:
  3334 00001C25 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3335 00001C28 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3336 00001C2A 80BF[896B0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3337 00001C31 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3338 00001C33 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3339 00001C36 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3340 00001C39 A0[886B0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3341 00001C3E D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3342 00001C40 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3343 00001C42 80A7[896B0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3344 00001C49 0887[896B0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3345                              <1> XN_OUT:
  3346 00001C4F C3                  <1> 	RETn
  3347                              <1> DO_DET:
  3348 00001C50 E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3349 00001C55 C3                  <1> 	RETn
  3350                              <1> 
  3351                              <1> ;-------------------------------------------------------------------------------
  3352                              <1> ; XLAT_OLD 
  3353                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3354                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3355                              <1> ;
  3356                              <1> ; ON ENTRY:	DI = DRIVE
  3357                              <1> ;-------------------------------------------------------------------------------
  3358                              <1> XLAT_OLD:
  3359 00001C56 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3360                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3361                              <1>         ;ja	XO_OUT
  3362                              <1>         ; 24/12/2021
  3363 00001C59 77F4                <1> 	ja	short XN_OUT
  3364 00001C5B 80BF[896B0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3365 00001C62 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3366                              <1> 
  3367                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3368                              <1> 
  3369 00001C64 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3370 00001C67 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3371 00001C6A B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3372 00001C6C D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3373 00001C6E 8425[886B0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3374 00001C74 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3375                              <1> 
  3376                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3377                              <1> 
  3378 00001C76 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3379 00001C78 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3380 00001C7A F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3381 00001C7C 2025[886B0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3382                              <1> 
  3383                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3384                              <1> 
  3385 00001C82 8A87[896B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3386 00001C88 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3387 00001C8A D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3388 00001C8C 0805[886B0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3389                              <1> 
  3390                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3391                              <1> 
  3392                              <1> SAVE_SET:
  3393 00001C92 8AA7[896B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3394 00001C98 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3395 00001C9A 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3396 00001C9D 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3397 00001CA0 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3398 00001CA2 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3399 00001CA4 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3400 00001CA7 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3401 00001CA9 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3402 00001CAC 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3403                              <1> UNKNO:
  3404 00001CAE B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3405 00001CB0 EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3406                              <1> CHK_144:
  3407 00001CB2 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3408                              <1> 	;;20/02/2015
  3409                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3410 00001CB7 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3411 00001CB9 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3412 00001CBB 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3413 00001CBD B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3414 00001CBF EB0C                <1> 	JMP	SHORT TST_DET
  3415                              <1> CHK_250:
  3416 00001CC1 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3417 00001CC3 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3418 00001CC6 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3419 00001CC8 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3420 00001CCB 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3421                              <1> TST_DET:
  3422 00001CCD F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3423 00001CD0 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3424 00001CD2 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3425                              <1> AL_SET:
  3426 00001CD4 80A7[896B0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3427 00001CDB 0887[896B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3428                              <1> XO_OUT:
  3429 00001CE1 C3                  <1> 	RETn
  3430                              <1> 
  3431                              <1> ;-------------------------------------------------------------------------------
  3432                              <1> ; RD_WR_VF
  3433                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3434                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3435                              <1> ;
  3436                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3437                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3438                              <1> ;
  3439                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3440                              <1> ;-------------------------------------------------------------------------------
  3441                              <1> RD_WR_VF:
  3442                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3443 00001CE2 50                  <1> 	push	eax ; 24/12/2021
  3444 00001CE3 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3445 00001CE8 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3446                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3447 00001CED 58                  <1> 	pop	eax ; 24/12/2021
  3448                              <1> DO_AGAIN:
  3449                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3450 00001CEE 50                  <1> 	push	eax ; 24/12/2021
  3451 00001CEF E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3452                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3453 00001CF4 58                  <1> 	pop	eax ; 24/12/2021
  3454                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3455                              <1> 	; 24/12/2021
  3456 00001CF5 7305                <1> 	jnc	short RWV
  3457 00001CF7 E9C3000000          <1> 	jmp	RWV_END
  3458                              <1> RWV:
  3459                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3460 00001CFC 50                  <1> 	push	eax ; 24/12/2021
  3461 00001CFD 8AB7[896B0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3462 00001D03 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3463 00001D06 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3464                              <1> 	;;20/02/2015
  3465                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3466 00001D0B 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3467 00001D0D 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3468 00001D0F 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3469 00001D11 F687[896B0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3470 00001D18 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3471 00001D1A B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3472 00001D1C EB0F                <1> 	JMP	SHORT RWV_2
  3473                              <1> RWV_1:
  3474 00001D1E 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3475 00001D20 F687[896B0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3476 00001D27 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3477 00001D29 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3478 00001D2B EB04                <1> 	jmp	short rwv_3
  3479                              <1> RWV_2:
  3480 00001D2D 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3481 00001D2F 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3482                              <1> rwv_3:
  3483 00001D31 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3484 00001D36 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3485                              <1> 
  3486                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3487                              <1> 
  3488 00001D38 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3489 00001D39 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3490 00001D3B B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3491                              <1> RWV_DR_SEARCH:
  3492 00001D40 8AA3[6C650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3493 00001D46 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3494 00001D49 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3495 00001D4B 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3496                              <1> RWV_DR_FND:
  3497 00001D4D 8BBB[6D650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3498                              <1> RWV_MD_SEARH:
  3499 00001D53 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3500 00001D56 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3501                              <1> RWV_NXT_MD:
  3502                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3503 00001D58 83C305              <1> 	add	eBX, 5
  3504 00001D5B E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3505 00001D5D 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3506                              <1> 
  3507                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3508                              <1> 
  3509                              <1> RWV_ASSUME:
  3510 00001D5E BB[8A650000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3511 00001D63 F687[896B0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3512 00001D6A 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3513 00001D6C BB[A4650000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3514 00001D71 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3515                              <1> 
  3516                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3517                              <1> 	 			
  3518                              <1> RWV_MD_FND:
  3519 00001D73 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3520 00001D75 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3521                              <1> 	
  3522                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3523                              <1> 
  3524                              <1> RWV_MD_FND1:
  3525 00001D76 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3526 00001D7B E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3527 00001D80 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3528 00001D82 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3529                              <1> RWV_DBL:
  3530 00001D87 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3531 00001D88 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3532 00001D8D 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3533 00001D8E 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3534                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3535 00001D90 58                  <1> 	pop	eax ; 24/12/2021
  3536                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3537 00001D91 50                  <1> 	push	eax ; 24/12/2021
  3538 00001D92 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3539 00001D93 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3540 00001D98 5B                  <1> 	POP	eBX 
  3541                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3542 00001D99 58                  <1> 	pop	eax ; 24/12/2021
  3543 00001D9A 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3544                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3545 00001D9C 50                  <1> 	push	eax ; 24/12/2021
  3546 00001D9D 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3547 00001D9E E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3548 00001DA3 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3549 00001DA4 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3550 00001DA6 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3551 00001DAB 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3552 00001DAD E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3553                              <1> CHK_RET:
  3554 00001DB2 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3555                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3556 00001DB7 58                  <1> 	pop	eax ; 24/12/2021
  3557 00001DB8 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3558 00001DBA E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3559                              <1> RWV_END:
  3560 00001DBF E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3561 00001DC4 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3562                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3563                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3564 00001DC9 50                  <1> 	push	eax ; 24/12/2021
  3565 00001DCA E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3566                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3567 00001DCF 58                  <1> 	pop	eax ; 24/12/2021
  3568 00001DD0 E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3569 00001DD5 C3                  <1> 	RETn
  3570                              <1> 
  3571                              <1> ;-------------------------------------------------------------------------------
  3572                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3573                              <1> ;-------------------------------------------------------------------------------
  3574                              <1> SETUP_STATE:
  3575 00001DD6 F687[896B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3576 00001DDD 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3577 00001DDF 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3578 00001DE3 F687[896B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3579 00001DEA 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3580 00001DEC F687[896B0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3581 00001DF3 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3582 00001DF5 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3583                              <1> AX_SET:	
  3584 00001DF9 80A7[896B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3585 00001E00 08A7[896B0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3586 00001E06 8025[846B0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3587 00001E0D C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3588 00001E10 0805[846B0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3589                              <1> J1C:	
  3590 00001E16 C3                  <1> 	RETn
  3591                              <1> 
  3592                              <1> ;-------------------------------------------------------------------------------
  3593                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3594                              <1> ;-------------------------------------------------------------------------------
  3595                              <1> FMT_INIT:
  3596 00001E17 F687[896B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3597 00001E1E 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3598 00001E20 E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3599                              <1> 	;; 20/02/2015
  3600                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3601 00001E25 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3602 00001E27 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3603                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3604 00001E29 8AA7[896B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3605 00001E2F 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3606 00001E32 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3607 00001E34 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3608 00001E36 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3609 00001E39 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3610                              <1> N_360:	
  3611 00001E3B FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3612 00001E3D 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3613                              <1> F1_RATE:
  3614 00001E3F 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3615 00001E42 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3616                              <1> N_12:	
  3617 00001E44 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3618 00001E46 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3619 00001E48 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3620 00001E4B 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3621 00001E4D F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3622 00001E50 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3623 00001E52 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3624 00001E55 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3625                              <1> N_720:
  3626 00001E57 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3627 00001E59 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3628 00001E5B EBE2                <1> 	JMP	SHORT F1_RATE
  3629                              <1> ISNT_12: 
  3630 00001E5D 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3631                              <1> 
  3632                              <1> SKP_STATE:
  3633 00001E60 88A7[896B0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3634                              <1> F1_OUT:
  3635 00001E66 C3                  <1> 	RETn
  3636                              <1> CL_DRV:	
  3637 00001E67 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3638 00001E69 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3639                              <1> 
  3640                              <1> ;-------------------------------------------------------------------------------
  3641                              <1> ; MED_CHANGE	
  3642                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3643                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3644                              <1> ;
  3645                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3646                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3647                              <1> ;-------------------------------------------------------------------------------
  3648                              <1> MED_CHANGE:
  3649 00001E6B E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3650 00001E70 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3651 00001E72 80A7[896B0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3652                              <1> 
  3653                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3654                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3655                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3656                              <1> 
  3657 00001E79 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3658 00001E7C B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3659 00001E7E D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3660 00001E80 F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3661 00001E82 FA                  <1> 	CLI				; NO INTERRUPTS
  3662 00001E83 2005[7A6B0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3663 00001E89 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3664 00001E8A E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3665                              <1> 
  3666                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3667                              <1> 
  3668 00001E8F E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3669 00001E94 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3670 00001E96 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3671 00001E9B 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3672 00001E9D E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3673 00001EA2 C605[7C6B0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3674                              <1> OK1:
  3675 00001EA9 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3676 00001EAE 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3677                              <1> OK4:
  3678 00001EB0 C605[7C6B0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3679                              <1> OK2:		
  3680 00001EB7 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3681 00001EB8 C3                  <1> 	RETn
  3682                              <1> MC_OUT:
  3683 00001EB9 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3684 00001EBA C3                  <1> 	RETn
  3685                              <1> 
  3686                              <1> ;-------------------------------------------------------------------------------
  3687                              <1> ; SEND_RATE
  3688                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3689                              <1> ; ON ENTRY:	DI = DRIVE #
  3690                              <1> ; ON EXIT:	NONE
  3691                              <1> ; REGISTERS ALTERED: DX
  3692                              <1> ;-------------------------------------------------------------------------------
  3693                              <1> SEND_RATE:
  3694                              <1> 	;PUSH	AX			; SAVE REG.
  3695                              <1> 	; 24/12/2021
  3696 00001EBB 50                  <1> 	push	eax
  3697 00001EBC 8025[846B0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3698 00001EC3 8A87[896B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3699 00001EC9 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3700 00001ECB 0805[846B0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3701 00001ED1 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3702 00001ED4 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3703 00001ED8 EE                  <1> 	OUT	DX,AL
  3704                              <1> 	;POP	AX			; RESTORE REG.
  3705                              <1> 	; 24/12/2021
  3706 00001ED9 58                  <1> 	pop	eax
  3707 00001EDA C3                  <1> 	RETn
  3708                              <1> 
  3709                              <1> ;-------------------------------------------------------------------------------
  3710                              <1> ; CHK_LASTRATE
  3711                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3712                              <1> ; ON ENTRY:
  3713                              <1> ;	DI = DRIVE #
  3714                              <1> ; ON EXIT:
  3715                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3716                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3717                              <1> ; REGISTERS ALTERED: DX
  3718                              <1> ;-------------------------------------------------------------------------------
  3719                              <1> CHK_LASTRATE:
  3720                              <1> 	;PUSH	AX			; SAVE REG.
  3721                              <1> 	; 24/12/2021
  3722 00001EDB 50                  <1> 	push	eax
  3723 00001EDC 2225[846B0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3724 00001EE2 8A87[896B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3725 00001EE8 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3726 00001EEC 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3727                              <1> 					; ZF = 1 RATE IS THE SAME
  3728                              <1> 	;POP	AX			; RESTORE REG.
  3729                              <1> 	; 24/12/2021
  3730 00001EEE 58                  <1> 	pop	eax
  3731 00001EEF C3                  <1> 	RETn
  3732                              <1> 
  3733                              <1> ;-------------------------------------------------------------------------------
  3734                              <1> ; DMA_SETUP
  3735                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3736                              <1> ;
  3737                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3738                              <1> ;
  3739                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3740                              <1> ;-------------------------------------------------------------------------------
  3741                              <1> 
  3742                              <1> ; SI = Head #, # of Sectors or DASD Type
  3743                              <1> 
  3744                              <1> ; 22/08/2015
  3745                              <1> ; 08/02/2015 - Protected Mode Modification
  3746                              <1> ; 06/02/2015 - 07/02/2015
  3747                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3748                              <1> ; (DMA Addres = Physical Address)
  3749                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3750                              <1> ;
  3751                              <1> ; 04/02/2016 (clc)
  3752                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3753                              <1> ; 16/12/2014 (IODELAY)
  3754                              <1> 
  3755                              <1> DMA_SETUP:
  3756                              <1> 
  3757                              <1> ;; 20/02/2015
  3758 00001EF0 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3759 00001EF3 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3760 00001EF9 7569                <1> 	jnz	short dma_bnd_err_stc
  3761                              <1> 	;
  3762                              <1> 	;push	ax			; DMA command
  3763                              <1> 	; 24/12/2021
  3764 00001EFB 50                  <1> 	push	eax
  3765 00001EFC 52                  <1> 	push	edx			; *
  3766 00001EFD B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3767 00001EFF E840030000          <1> 	call	GET_PARM		; 
  3768 00001F04 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3769                              <1> 	;mov	ax, si			; Sector count
  3770                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3771                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3772                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3773                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3774                              <1> 	; 24/12/2021
  3775 00001F06 89F2                <1> 	mov	edx, esi
  3776 00001F08 29C0                <1> 	sub	eax, eax
  3777 00001F0A 88D4                <1> 	mov	ah, dl
  3778 00001F0C D1E8                <1> 	shr	eax, 1
  3779 00001F0E D3E0                <1> 	shl	eax, cl
  3780                              <1> 	;
  3781 00001F10 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3782 00001F12 6689C1              <1> 	mov	cx, ax
  3783 00001F15 5A                  <1> 	pop	edx			; *
  3784                              <1> 	;pop	ax
  3785                              <1> 	; 24/12/2021
  3786 00001F16 58                  <1> 	pop	eax
  3787 00001F17 3C42                <1> 	cmp	al, 42h
  3788 00001F19 7507                <1>         jne     short NOT_VERF
  3789 00001F1B BA0000FF00          <1> 	mov	edx, 0FF0000h
  3790 00001F20 EB08                <1> 	jmp	short J33
  3791                              <1> NOT_VERF:
  3792 00001F22 6601CA              <1> 	add	dx, cx			; check for overflow
  3793 00001F25 723E                <1> 	jc	short dma_bnd_err
  3794                              <1> 	;
  3795 00001F27 6629CA              <1> 	sub	dx, cx			; Restore start address
  3796                              <1> J33:
  3797 00001F2A FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3798 00001F2B E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3799                              <1> 	IODELAY				; WAIT FOR I/O
  2141 00001F2D EB00                <2>  jmp short $+2
  2142 00001F2F EB00                <2>  jmp short $+2
  3800 00001F31 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3801 00001F33 89D0                <1> 	mov	eax,edx			; Buffer address
  3802 00001F35 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3803                              <1> 	IODELAY				; WAIT FOR I/O
  2141 00001F37 EB00                <2>  jmp short $+2
  2142 00001F39 EB00                <2>  jmp short $+2
  3804 00001F3B 88E0                <1> 	MOV	AL,AH
  3805 00001F3D E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3806 00001F3F C1E810              <1> 	shr	eax,16
  3807                              <1> 	IODELAY				; I/O WAIT STATE
  2141 00001F42 EB00                <2>  jmp short $+2
  2142 00001F44 EB00                <2>  jmp short $+2
  3808 00001F46 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3809                              <1> 	IODELAY
  2141 00001F48 EB00                <2>  jmp short $+2
  2142 00001F4A EB00                <2>  jmp short $+2
  3810 00001F4C 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3811 00001F4F E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3812                              <1> 	IODELAY				; WAIT FOR I/O
  2141 00001F51 EB00                <2>  jmp short $+2
  2142 00001F53 EB00                <2>  jmp short $+2
  3813 00001F55 88E0                <1> 	MOV	AL,AH
  3814 00001F57 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3815                              <1> 	IODELAY
  2141 00001F59 EB00                <2>  jmp short $+2
  2142 00001F5B EB00                <2>  jmp short $+2
  3816 00001F5D FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3817 00001F5E B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3818 00001F60 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3819                              <1> 
  3820 00001F62 F8                  <1> 	clc	; 04/02/2016
  3821 00001F63 C3                  <1> 	retn
  3822                              <1> 
  3823                              <1> dma_bnd_err_stc:
  3824 00001F64 F9                  <1> 	stc
  3825                              <1> dma_bnd_err:
  3826 00001F65 C605[7C6B0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3827 00001F6C C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3828                              <1> 
  3829                              <1> ;; 16/12/2014
  3830                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3831                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3832                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3833                              <1> ;;	IODELAY
  3834                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3835                              <1> ;;	;SIODELAY
  3836                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3837                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3838                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3839                              <1> ;;      ;JMP	SHORT J33
  3840                              <1> ;;;NOT_VERF:	
  3841                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3842                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3843                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3844                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3845                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3846                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3847                              <1> ;;	;JNC	short J33
  3848                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3849                              <1> ;;;J33:
  3850                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3851                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3852                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3853                              <1> ;;	IODELAY
  3854                              <1> ;;	MOV	AL,AH
  3855                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3856                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3857                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3858                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3859                              <1> ;;	IODELAY
  3860                              <1> ;;	;AND	AL,00001111B
  3861                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3862                              <1> ;;	;SIODELAY
  3863                              <1> ;;
  3864                              <1> ;;;----- DETERMINE COUNT
  3865                              <1> ;;	sub	eax, eax ; 08/02/2015
  3866                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3867                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3868                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3869                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3870                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3871                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3872                              <1> ;;	CALL	GET_PARM		; "
  3873                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3874                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3875                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3876                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3877                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3878                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3879                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3880                              <1> ;;	IODELAY
  3881                              <1> ;;	MOV	AL, AH
  3882                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3883                              <1> ;;	;IODELAY
  3884                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3885                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3886                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3887                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3888                              <1> ;;	add	ecx, eax ; 08/02/2015
  3889                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3890                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3891                              <1> ;;	SIODELAY
  3892                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3893                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3894                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3895                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3896                              <1> ;;	jz	short NO_BAD
  3897                              <1> ;;dma_bnd_err:
  3898                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3899                              <1> ;;NO_BAD:
  3900                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3901                              <1> 
  3902                              <1> ;-------------------------------------------------------------------------------
  3903                              <1> ; FMTDMA_SET
  3904                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3905                              <1> ;
  3906                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3907                              <1> ;
  3908                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3909                              <1> ;-------------------------------------------------------------------------------
  3910                              <1> 
  3911                              <1> 	; 24/12/2021
  3912                              <1> FMTDMA_SET:
  3913                              <1> ;; 20/02/2015 modification	
  3914 00001F6D 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3915 00001F70 F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3916 00001F76 75EC                <1> 	jnz	short dma_bnd_err_stc
  3917                              <1> 	;
  3918                              <1> 	;push	dx			; *
  3919                              <1> 	; 24/12/2021
  3920 00001F78 52                  <1> 	push	edx
  3921 00001F79 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3922 00001F7B E8C4020000          <1> 	call	GET_PARM		; "
  3923                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3924                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3925                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3926                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3927                              <1> 	;mov	cx, ax
  3928                              <1> 	; 24/12/2021
  3929 00001F80 29C9                <1> 	sub	ecx, ecx
  3930 00001F82 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3931 00001F84 D1E1                <1> 	shl	ecx, 1
  3932 00001F86 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3933 00001F88 6649                <1> 	dec	cx
  3934                              <1> 	;pop	dx			; *
  3935                              <1> 	; 24/12/2021
  3936 00001F8A 5A                  <1> 	pop	edx
  3937 00001F8B 6601CA              <1> 	add	dx, cx			; check for overflow
  3938 00001F8E 72D5                <1> 	jc	short dma_bnd_err
  3939                              <1> 	;
  3940 00001F90 6629CA              <1> 	sub	dx, cx			; Restore start address
  3941                              <1> 	;
  3942 00001F93 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3943 00001F95 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3944 00001F96 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3945                              <1> 	IODELAY				; WAIT FOR I/O
  2141 00001F98 EB00                <2>  jmp short $+2
  2142 00001F9A EB00                <2>  jmp short $+2
  3946 00001F9C E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3947 00001F9E 89D0                <1> 	mov	eax,edx			; Buffer address
  3948 00001FA0 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3949                              <1> 	IODELAY				; WAIT FOR I/O
  2141 00001FA2 EB00                <2>  jmp short $+2
  2142 00001FA4 EB00                <2>  jmp short $+2
  3950 00001FA6 88E0                <1> 	MOV	AL,AH
  3951 00001FA8 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3952 00001FAA C1E810              <1> 	shr	eax,16
  3953                              <1> 	IODELAY				; I/O WAIT STATE
  2141 00001FAD EB00                <2>  jmp short $+2
  2142 00001FAF EB00                <2>  jmp short $+2
  3954 00001FB1 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3955                              <1> 	IODELAY
  2141 00001FB3 EB00                <2>  jmp short $+2
  2142 00001FB5 EB00                <2>  jmp short $+2
  3956 00001FB7 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3957 00001FBA E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3958                              <1> 	IODELAY				; WAIT FOR I/O
  2141 00001FBC EB00                <2>  jmp short $+2
  2142 00001FBE EB00                <2>  jmp short $+2
  3959 00001FC0 88E0                <1> 	MOV	AL,AH
  3960 00001FC2 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3961                              <1> 	IODELAY
  2141 00001FC4 EB00                <2>  jmp short $+2
  2142 00001FC6 EB00                <2>  jmp short $+2
  3962 00001FC8 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3963 00001FC9 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3964 00001FCB E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3965 00001FCD C3                  <1> 	retn
  3966                              <1> 
  3967                              <1> ;; 08/02/2015 - Protected Mode Modification
  3968                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3969                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3970                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3971                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3972                              <1> ;;	IODELAY
  3973                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3974                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3975                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3976                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3977                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3978                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3979                              <1> ;;	;JNC	short J33A
  3980                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3981                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3982                              <1> ;;;J33A:
  3983                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3984                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3985                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3986                              <1> ;;	IODELAY
  3987                              <1> ;;	MOV	AL,AH
  3988                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3989                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3990                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3991                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3992                              <1> ;;	IODELAY
  3993                              <1> ;;	;AND	AL,00001111B
  3994                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3995                              <1> ;;
  3996                              <1> ;;;----- DETERMINE COUNT
  3997                              <1> ;;	sub	eax, eax ; 08/02/2015
  3998                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3999                              <1> ;;	CALL	GET_PARM		; "
  4000                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  4001                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  4002                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  4003                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  4004                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  4005                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  4006                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4007                              <1> ;;	IODELAY
  4008                              <1> ;;	MOV	AL, AH
  4009                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  4010                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  4011                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  4012                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  4013                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  4014                              <1> ;;	add	ecx, eax ; 08/02/2015
  4015                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  4016                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4017                              <1> ;;	SIODELAY
  4018                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  4019                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  4020                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  4021                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  4022                              <1> ;;	jz	short FMTDMA_OK
  4023                              <1> ;;	stc	; 20/02/2015
  4024                              <1> ;;fmtdma_bnd_err:
  4025                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  4026                              <1> ;;FMTDMA_OK:
  4027                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  4028                              <1> 
  4029                              <1> ;-------------------------------------------------------------------------------
  4030                              <1> ; NEC_INIT	
  4031                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  4032                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  4033                              <1> ;
  4034                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  4035                              <1> ;
  4036                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4037                              <1> ;-------------------------------------------------------------------------------
  4038                              <1> NEC_INIT:
  4039                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4040                              <1> 	; 24/12/2021
  4041 00001FCE 50                  <1> 	push	eax
  4042 00001FCF E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4043                              <1> 
  4044                              <1> ;-----	DO THE SEEK OPERATION
  4045                              <1> 
  4046 00001FD4 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4047 00001FD7 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4048                              <1> 	;POP	AX			; RECOVER COMMAND
  4049                              <1> 	; 24/12/2021
  4050 00001FDC 58                  <1> 	pop	eax
  4051 00001FDD 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4052 00001FDF BB[FD1F0000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4053 00001FE4 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4054                              <1> 
  4055                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4056                              <1> 
  4057 00001FE5 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4058 00001FEA 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4059 00001FED 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4060 00001FEF C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4061 00001FF2 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4062 00001FF5 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4063 00001FF7 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4064 00001FFC 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4065                              <1> ER_1:
  4066 00001FFD C3                  <1> 	RETn
  4067                              <1> 
  4068                              <1> ;-------------------------------------------------------------------------------
  4069                              <1> ; RWV_COM
  4070                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4071                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4072                              <1> ;
  4073                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4074                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4075                              <1> ;-------------------------------------------------------------------------------
  4076                              <1> RWV_COM:
  4077 00001FFE B8[49200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4078 00002003 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4079 00002004 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4080 00002007 E83E030000          <1> 	CALL	NEC_OUTPUT
  4081 0000200C 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4082 0000200F E836030000          <1> 	CALL	NEC_OUTPUT
  4083 00002014 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4084 00002017 E82E030000          <1> 	CALL	NEC_OUTPUT
  4085 0000201C B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4086 0000201E E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4087 00002023 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4088 00002028 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4089 0000202A E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4090 0000202F E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4091 00002034 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4092                              <1> _R15:
  4093 00002037 E80E030000          <1> 	CALL	NEC_OUTPUT
  4094 0000203C B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4095 0000203E E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4096 00002043 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4097 00002048 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4098                              <1> ER_2:
  4099 00002049 C3                  <1> 	RETn
  4100                              <1> 
  4101                              <1> ;-------------------------------------------------------------------------------
  4102                              <1> ; NEC_TERM
  4103                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4104                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4105                              <1> ;
  4106                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4107                              <1> ;-------------------------------------------------------------------------------
  4108                              <1> NEC_TERM:
  4109                              <1> 
  4110                              <1> ;-----	LET THE OPERATION HAPPEN
  4111                              <1> 
  4112 0000204A 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4113 0000204B E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4114 00002050 9C                  <1> 	PUSHFd	; 24/12/2021
  4115 00002051 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4116 00002056 724B                <1> 	JC	short SET_END_POP
  4117 00002058 9D                  <1> 	POPFd	; 24/12/2021
  4118 00002059 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4119                              <1> 
  4120                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4121                              <1> 
  4122 0000205B FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4123 0000205C BE[7D6B0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4124 00002061 AC                  <1> 	lodsb				; GET ST0
  4125 00002062 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4126 00002064 7433                <1> 	JZ	short SET_END
  4127 00002066 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4128 00002068 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4129                              <1> 
  4130                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4131                              <1> 
  4132 0000206A AC                  <1> 	lodsb				; GET ST1
  4133 0000206B D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4134 0000206D B404                <1> 	MOV	AH,RECORD_NOT_FND
  4135 0000206F 7222                <1> 	JC	short J19
  4136 00002071 C0E002              <1> 	SAL	AL,2
  4137 00002074 B410                <1> 	MOV	AH,BAD_CRC
  4138 00002076 721B                <1> 	JC	short J19
  4139 00002078 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4140 0000207A B408                <1> 	MOV	AH,BAD_DMA
  4141 0000207C 7215                <1> 	JC	short J19
  4142 0000207E C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4143 00002081 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4144 00002083 720E                <1> 	JC	short J19
  4145 00002085 D0E0                <1> 	SAL	AL,1
  4146 00002087 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4147 00002089 7208                <1> 	JC	short J19
  4148 0000208B D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4149 0000208D B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4150 0000208F 7202                <1> 	JC	short J19
  4151                              <1> 
  4152                              <1> ;----- 	NEC MUST HAVE FAILED
  4153                              <1> J18:
  4154 00002091 B420                <1> 	MOV	AH,BAD_NEC
  4155                              <1> J19:
  4156 00002093 0825[7C6B0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4157                              <1> SET_END:
  4158 00002099 803D[7C6B0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4159 000020A0 F5                  <1> 	CMC
  4160 000020A1 5E                  <1> 	POP	eSI
  4161 000020A2 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4162                              <1> 
  4163                              <1> SET_END_POP:
  4164 000020A3 9D                  <1> 	POPFd	; 24/12/2021
  4165 000020A4 EBF3                <1> 	JMP	SHORT SET_END
  4166                              <1> 
  4167                              <1> ;-------------------------------------------------------------------------------
  4168                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4169                              <1> ;-------------------------------------------------------------------------------
  4170                              <1> DSTATE:
  4171 000020A6 803D[7C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4172 000020AD 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4173 000020AF 808F[896B0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4174 000020B6 F687[896B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4175 000020BD 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4176 000020BF 8A87[896B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4177 000020C5 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4178 000020C7 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4179 000020C9 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4180                              <1> 
  4181                              <1> ;----- 	CHECK IF IT IS 1.44M
  4182                              <1> 
  4183 000020CB E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4184                              <1> 	;;20/02/2015
  4185                              <1> 	;;JC	short M_12		; CMOS BAD
  4186 000020D0 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4187 000020D2 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4188 000020D4 7410                <1> 	JE	short M_12		; YES
  4189                              <1> M_720:
  4190 000020D6 80A7[896B0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4191 000020DD 808F[896B0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4192 000020E4 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4193                              <1> M_12:	
  4194 000020E6 808F[896B0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4195                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4196                              <1> SETBAC:
  4197 000020ED C3                  <1> 	RETn
  4198                              <1> 
  4199                              <1> ;-------------------------------------------------------------------------------
  4200                              <1> ; RETRY	
  4201                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4202                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4203                              <1> ;
  4204                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4205                              <1> ;-------------------------------------------------------------------------------
  4206                              <1> RETRY:
  4207 000020EE 803D[7C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4208 000020F5 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4209 000020F7 803D[7C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4210 000020FE 743C                <1> 	JZ	short NO_RETRY
  4211 00002100 8AA7[896B0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4212 00002106 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4213 00002109 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4214 0000210B 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4215 0000210E 8A2D[846B0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4216 00002114 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4217 00002117 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4218 0000211A 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4219 0000211C 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4220                              <1> 
  4221                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4222                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4223                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4224                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4225                              <1> 
  4226 0000211E 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4227 00002121 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4228 00002123 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4229 00002126 80A7[896B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4230                              <1> 					; RATE, DBL STEP OFF
  4231 0000212D 08A7[896B0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4232 00002133 C605[7C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4233 0000213A F9                  <1> 	STC				; SET CARRY FOR RETRY
  4234 0000213B C3                  <1> 	RETn				; RETRY RETURN
  4235                              <1> 
  4236                              <1> NO_RETRY:
  4237 0000213C F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4238 0000213D C3                  <1> 	RETn				; NO RETRY RETURN
  4239                              <1> 
  4240                              <1> ;-------------------------------------------------------------------------------
  4241                              <1> ; NUM_TRANS
  4242                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4243                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4244                              <1> ;
  4245                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4246                              <1> ;		SI-HI  = HEAD
  4247                              <1> ;		[BP]   = START SECTOR
  4248                              <1> ;
  4249                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4250                              <1> ;-------------------------------------------------------------------------------
  4251                              <1> NUM_TRANS:
  4252 0000213E 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4253 00002140 803D[7C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4254                              <1> 	; 24/12/2021
  4255 00002147 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4256 00002149 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4257 0000214B E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4258 00002150 8A1D[826B0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4259 00002156 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4260 00002159 3A2D[816B0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4261 0000215F 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4262 00002161 8A2D[806B0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4263 00002167 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4264 0000216A 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4265 0000216C 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4266                              <1> DIF_HD:
  4267 0000216E 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4268                              <1> SAME_TRK:
  4269 00002170 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4270 00002173 88D8                <1> 	MOV	AL,BL			; TO AL
  4271                              <1> NT_OUT:
  4272 00002175 C3                  <1> 	RETn
  4273                              <1> 
  4274                              <1> ;-------------------------------------------------------------------------------
  4275                              <1> ; SETUP_END
  4276                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4277                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4278                              <1> ;
  4279                              <1> ; ON EXIT:
  4280                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4281                              <1> ;-------------------------------------------------------------------------------
  4282                              <1> SETUP_END:
  4283 00002176 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4284                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4285 00002178 50                  <1> 	push	eax ; 24/12/2021
  4286 00002179 E8C6000000          <1> 	CALL	GET_PARM
  4287 0000217E 8825[7B6B0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4288                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4289 00002184 58                  <1> 	pop	eax ; 24/12/2021
  4290 00002185 8A25[7C6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4291 0000218B 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4292 0000218D 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4293 0000218F 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4294                              <1> NUN_ERR: 
  4295 00002191 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4296 00002194 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4297 00002195 C3                  <1> 	RETn
  4298                              <1> 
  4299                              <1> ;-------------------------------------------------------------------------------
  4300                              <1> ; SETUP_DBL
  4301                              <1> ;	CHECK DOUBLE STEP.
  4302                              <1> ;
  4303                              <1> ; ON ENTRY :	DI = DRIVE
  4304                              <1> ;
  4305                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4306                              <1> ;-------------------------------------------------------------------------------
  4307                              <1> SETUP_DBL:
  4308 00002196 8AA7[896B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4309 0000219C F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4310 0000219F 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4311                              <1> 
  4312                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4313                              <1> 
  4314 000021A1 C605[796B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4315 000021A8 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4316 000021AD B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4317 000021AF E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4318 000021B4 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4319 000021B9 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4320                              <1> 
  4321                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4322                              <1> 
  4323 000021BB 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4324 000021BF F687[896B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4325 000021C6 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4326 000021C8 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4327                              <1> 
  4328                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4329                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4330                              <1> ;	THEN SET DOUBLE STEP ON.
  4331                              <1> 
  4332                              <1> CNT_OK:
  4333 000021CA C605[7B6B0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4334                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4335                              <1> 	; 24/12/2021
  4336 000021D1 51                  <1> 	push	ecx
  4337 000021D2 C605[7C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4338 000021D9 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4339 000021DC D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4340 000021DE C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4341                              <1> 	;PUSH	AX			; SAVE HEAD
  4342                              <1> 	; 24/12/2021
  4343 000021E1 50                  <1> 	push	eax
  4344 000021E2 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4345                              <1> 	;POP	AX			; RESTORE HEAD
  4346                              <1> 	; 24/12/2021
  4347 000021E7 58                  <1> 	pop	eax
  4348 000021E8 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4349 000021EB E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4350 000021F0 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4351 000021F1 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4352 000021F6 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4353                              <1> 	;POP	CX			; RESTORE COUNT
  4354                              <1> 	; 24/12/2021
  4355 000021F7 59                  <1> 	pop	ecx
  4356 000021F8 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4357 000021FA FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4358 000021FC 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4359 000021FE 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4360                              <1> 
  4361                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4362                              <1> 
  4363                              <1> SD_ERR:	
  4364 00002200 F9                  <1> 	STC				; SET CARRY FOR ERROR
  4365 00002201 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4366                              <1> 
  4367                              <1> DO_CHK:
  4368 00002202 8A0D[806B0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4369 00002208 888F[8D6B0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4370 0000220E D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4371 00002210 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4372 00002212 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4373 00002214 808F[896B0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4374                              <1> NO_DBL:
  4375 0000221B F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4376 0000221C C3                  <1> 	RETn
  4377                              <1> 
  4378                              <1> ;-------------------------------------------------------------------------------
  4379                              <1> ; READ_ID
  4380                              <1> ;	READ ID FUNCTION.
  4381                              <1> ;
  4382                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4383                              <1> ;
  4384                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4385                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4386                              <1> ;-------------------------------------------------------------------------------
  4387                              <1> READ_ID:
  4388 0000221D B8[3A220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4389 00002222 50                  <1> 	PUSH	eAX
  4390 00002223 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4391 00002225 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4392 0000222A 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4393 0000222D 88C4                <1> 	MOV	AH,AL
  4394 0000222F E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4395 00002234 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4396 00002239 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4397                              <1> ER_3:
  4398 0000223A C3                  <1> 	RETn
  4399                              <1> 
  4400                              <1> ;-------------------------------------------------------------------------------
  4401                              <1> ; CMOS_TYPE
  4402                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4403                              <1> ;
  4404                              <1> ; ON ENTRY:	DI = DRIVE #
  4405                              <1> ;
  4406                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4407                              <1> ;-------------------------------------------------------------------------------
  4408                              <1> 
  4409                              <1> CMOS_TYPE: ; 11/12/2014
  4410 0000223B 8A87[EE650000]      <1> 	mov	al, [eDI+fd0_type]
  4411 00002241 20C0                <1> 	and 	al, al ; 18/12/2014
  4412 00002243 C3                  <1> 	retn
  4413                              <1> 
  4414                              <1> ;CMOS_TYPE:
  4415                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4416                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4417                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4418                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4419                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4420                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4421                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4422                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4423                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4424                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4425                              <1> ;TB:
  4426                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4427                              <1> ;BAD_CM:
  4428                              <1> ;	RETn				; CY, STATUS OF READ
  4429                              <1> 
  4430                              <1> ;-------------------------------------------------------------------------------
  4431                              <1> ; GET_PARM
  4432                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4433                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4434                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4435                              <1> ;	THE PARAMETER IN DL.
  4436                              <1> ;
  4437                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4438                              <1> ;
  4439                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4440                              <1> ;		AL,DH DESTROYED
  4441                              <1> ;-------------------------------------------------------------------------------
  4442                              <1> GET_PARM:
  4443                              <1> 	;PUSH	DS
  4444 00002244 56                  <1> 	PUSH	eSI
  4445                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4446                              <1>     	;MOV	DS,AX
  4447                              <1> 	;;mov	ax, cs
  4448                              <1> 	;;mov	ds, ax
  4449                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4450 00002245 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4451                              <1> 	;SUB	BH,BH			; BX = INDEX
  4452 00002247 81E3FF000000        <1> 	and	ebx, 0FFh
  4453                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4454                              <1> 	;
  4455                              <1> 	; 17/12/2014
  4456 0000224D 66A1[E1650000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4457 00002253 38E0                <1> 	cmp	al, ah
  4458 00002255 7425                <1> 	je	short gpndc
  4459 00002257 A2[E2650000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4460 0000225C 53                  <1> 	push	ebx ; 08/02/2015
  4461 0000225D 88C3                <1> 	mov	bl, al 
  4462                              <1> 	; 11/12/2014
  4463 0000225F 8A83[EE650000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4464                              <1> 	; 18/12/2014
  4465 00002265 20C0                <1> 	and	al, al
  4466 00002267 7507                <1> 	jnz	short gpdtc
  4467 00002269 BB[CB650000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4468 0000226E EB05                <1>         jmp     short gpdpu
  4469                              <1> gpdtc:	
  4470 00002270 E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4471                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4472                              <1> gpdpu:
  4473 00002275 891D[68650000]      <1> 	mov	[DISK_POINTER], ebx
  4474 0000227B 5B                  <1> 	pop	ebx
  4475                              <1> gpndc:
  4476 0000227C 8B35[68650000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4477 00002282 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4478 00002285 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4479 00002287 5E                  <1> 	POP	eSI
  4480                              <1> 	;POP	DS
  4481 00002288 C3                  <1> 	RETn
  4482                              <1> 
  4483                              <1> ;-------------------------------------------------------------------------------
  4484                              <1> ; MOTOR_ON
  4485                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4486                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4487                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4488                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4489                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4490                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4491                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4492                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4493                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4494                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4495                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4496                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4497                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4498                              <1> ;
  4499                              <1> ; ON ENTRY:	DI = DRIVE #
  4500                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4501                              <1> ;-------------------------------------------------------------------------------
  4502                              <1> MOTOR_ON:
  4503 00002289 53                  <1> 	PUSH	eBX			; SAVE REG.
  4504 0000228A E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4505 0000228F 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4506 00002291 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4507 00002296 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4508                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4509                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4510                              <1> M_WAIT:
  4511 0000229B B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4512 0000229D E8A2FFFFFF          <1> 	CALL	GET_PARM
  4513                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4514                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4515                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4516 000022A2 80FC08              <1> 	cmp	ah, 8
  4517                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4518 000022A5 7702                <1> 	ja	short J13
  4519                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4520 000022A7 B408                <1> 	mov	ah, 8
  4521                              <1> 
  4522                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4523                              <1> GP2:	
  4524                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4525                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4526 000022A9 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4527 000022AE E80BF2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4528                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4529 000022B3 FECC                <1> 	dec	ah
  4530 000022B5 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4531                              <1> MOT_IS_ON:
  4532 000022B7 5B                  <1> 	POP	eBX			; RESTORE REG.
  4533 000022B8 C3                  <1> 	RETn
  4534                              <1> 
  4535                              <1> ;-------------------------------------------------------------------------------
  4536                              <1> ; TURN_ON
  4537                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4538                              <1> ;
  4539                              <1> ; ON ENTRY:	DI = DRIVE #
  4540                              <1> ;
  4541                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4542                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4543                              <1> ;		AX,BX,CX,DX DESTROYED
  4544                              <1> ;-------------------------------------------------------------------------------
  4545                              <1> TURN_ON:
  4546 000022B9 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4547 000022BB 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4548 000022BD C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4549 000022C0 FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4550 000022C1 C605[7B6B0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4551 000022C8 A0[7A6B0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4552 000022CD 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4553 000022CF B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4554 000022D1 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4555                              <1> 
  4556                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4557                              <1> ;  BL = DRIVE SELECT DESIRED
  4558                              <1> ;  AH = MOTOR ON MASK DESIRED
  4559                              <1> 
  4560 000022D3 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4561 000022D5 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4562 000022D7 8425[7A6B0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4563 000022DD 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4564                              <1> 
  4565                              <1> TURN_IT_ON:
  4566 000022DF 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4567 000022E1 8A3D[7A6B0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4568 000022E7 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4569 000022EA 8025[7A6B0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4570 000022F1 0825[7A6B0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4571 000022F7 A0[7A6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4572 000022FC 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4573 000022FE 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4574 00002301 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4575 00002302 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4576 00002304 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4577 00002307 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4578 00002309 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4579 0000230D EE                  <1> 	OUT	DX,AL
  4580 0000230E 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4581                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4582 00002310 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4583 00002312 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4584 00002313 C3                  <1> 	RETn
  4585                              <1> 
  4586                              <1> NO_MOT_WAIT:
  4587 00002314 FB                  <1> 	sti
  4588                              <1> no_mot_w1: ; 27/02/2015
  4589 00002315 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4590                              <1> 	;STI				; INTERRUPTS BACK ON
  4591 00002316 C3                  <1> 	RETn
  4592                              <1> 
  4593                              <1> ;-------------------------------------------------------------------------------
  4594                              <1> ; HD_WAIT
  4595                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4596                              <1> ;
  4597                              <1> ; ON ENTRY:	DI = DRIVE #
  4598                              <1> ;
  4599                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4600                              <1> ;-------------------------------------------------------------------------------
  4601                              <1> HD_WAIT:
  4602 00002317 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4603 00002319 E826FFFFFF          <1> 	CALL	GET_PARM
  4604 0000231E 08E4                <1> 	or	ah, ah	; 17/12/2014
  4605 00002320 7519                <1> 	jnz	short DO_WAT
  4606 00002322 F605[7A6B0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4607                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4608                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4609                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4610 00002329 741E                <1> 	jz	short HW_DONE
  4611 0000232B B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4612 0000232D 8A87[896B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4613 00002333 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4614 00002335 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4615 00002337 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4616                              <1> ;GP3:
  4617 00002339 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4618                              <1> ;	JMP	SHORT DO_WAT
  4619                              <1> 
  4620                              <1> ;ISNT_WRITE:
  4621                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4622                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4623                              <1> 
  4624                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4625                              <1> DO_WAT:
  4626                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4627                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4628                              <1> J29:					; 	1 MILLISECOND LOOP
  4629                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4630 0000233B B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4631 00002340 E879F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4632                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4633 00002345 FECC                <1> 	dec	ah
  4634 00002347 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4635                              <1> HW_DONE:
  4636 00002349 C3                  <1> 	RETn
  4637                              <1> 
  4638                              <1> ;-------------------------------------------------------------------------------
  4639                              <1> ; NEC_OUTPUT
  4640                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4641                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4642                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4643                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4644                              <1> ; 
  4645                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4646                              <1> ;
  4647                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4648                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4649                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4650                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4651                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4652                              <1> ;		AX,CX,DX DESTROYED
  4653                              <1> ;-------------------------------------------------------------------------------
  4654                              <1> 
  4655                              <1> ; 09/12/2014 [Erdogan Tan] 
  4656                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4657                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4658                              <1> ;	This read only register facilitates the transfer of data between
  4659                              <1> ;	the system microprocessor and the controller.
  4660                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4661                              <1> ;	  with the system micrprocessor.
  4662                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4663                              <1> ;	  the transfer is to the controller.
  4664                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4665                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4666                              <1> ; Bit 3 - Reserved.
  4667                              <1> ; Bit 2 - Reserved.
  4668                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4669                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4670                              <1> 
  4671                              <1> ; Data Register (3F5h)
  4672                              <1> ; This read/write register passes data, commands and parameters, and provides
  4673                              <1> ; diskette status information.
  4674                              <1>   		
  4675                              <1> NEC_OUTPUT:
  4676                              <1> 	;PUSH	BX			; SAVE REG.
  4677 0000234A 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4678                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4679                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4680                              <1> 	; 16/12/2014
  4681                              <1> 	; waiting for (max.) 0.5 seconds
  4682                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4683                              <1> 	;
  4684                              <1> 	; 17/12/2014
  4685                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4686                              <1> 	;
  4687                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4688                              <1> 	;		go on.
  4689                              <1> 	;INPUT:
  4690                              <1> 	;	AH=Mask for isolation bits.
  4691                              <1> 	;	AL=pattern to look for.
  4692                              <1> 	;	DX=Port to test for
  4693                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4694                              <1> 	;	     (normally 30 microseconds per period.)
  4695                              <1> 	;
  4696                              <1> 	;WFP_SHORT:  
  4697                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4698                              <1> 	;
  4699                              <1> 
  4700                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4701                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4702 0000234E B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4703                              <1> ;
  4704                              <1> ;WFPS_OUTER_LP:
  4705                              <1> ;	;
  4706                              <1> ;WFPS_CHECK_PORT:
  4707                              <1> J23:
  4708 00002353 EC                  <1> 	IN	AL,DX			; GET STATUS
  4709 00002354 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4710 00002356 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4711 00002358 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4712                              <1> WFPS_HI:
  4713 0000235A E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4714 0000235C A810                <1> 	TEST	AL,010H			; transition on memory
  4715 0000235E 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4716                              <1> WFPS_LO:
  4717 00002360 E461                <1> 	IN	AL, PORT_B		; SYS1
  4718 00002362 A810                <1> 	TEST	AL,010H
  4719 00002364 74FA                <1> 	JZ	SHORT WFPS_LO
  4720                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4721 00002366 E2EB                <1> 	loop	J23	; 27/02/2015
  4722                              <1> ;	;
  4723                              <1> ;	dec	bl
  4724                              <1> ;	jnz	short WFPS_OUTER_LP
  4725                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4726                              <1> ;J23:
  4727                              <1> ;	IN	AL,DX			; GET STATUS
  4728                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4729                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4730                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4731                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4732                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4733                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4734                              <1>    
  4735                              <1> 	;;27/02/2015
  4736                              <1> 	;16/12/2014
  4737                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4738                              <1> 	;;jb	short J23
  4739                              <1> 
  4740                              <1> ;WFPS_TIMEOUT:
  4741                              <1> 
  4742                              <1> ;-----	FALL THRU TO ERROR RETURN
  4743                              <1> 
  4744 00002368 800D[7C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4745                              <1> 	;POP	BX			; RESTORE REG.
  4746 0000236F 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4747 00002370 F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4748 00002371 C3                  <1> 	RETn
  4749                              <1> 
  4750                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4751                              <1> 
  4752                              <1> J27:	
  4753 00002372 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4754 00002374 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4755 00002376 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4756                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4757                              <1> 	; 27/02/2015
  4758 00002377 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4759                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4760 00002378 29C9                <1> 	sub	ecx, ecx
  4761 0000237A B103                <1> 	mov	cl, 3 ; 24/12/2021
  4762 0000237C E83DF1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4763 00002381 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4764                              <1> 	;POP	BX			; RESTORE REG
  4765 00002382 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4766                              <1> 
  4767                              <1> ;-------------------------------------------------------------------------------
  4768                              <1> ; SEEK
  4769                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4770                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4771                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4772                              <1> ;
  4773                              <1> ; ON ENTRY:	DI = DRIVE #
  4774                              <1> ;		CH = TRACK #
  4775                              <1> ;
  4776                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4777                              <1> ;		AX,BX,CX DX DESTROYED
  4778                              <1> ;-------------------------------------------------------------------------------
  4779                              <1> SEEK:
  4780 00002383 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4781 00002385 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4782 00002387 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4783 00002389 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4784 0000238B 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4785 0000238D 8405[796B0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4786 00002393 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4787                              <1> 
  4788 00002395 0805[796B0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4789 0000239B E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4790 000023A0 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4791                              <1> 
  4792                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4793                              <1> 
  4794 000023A2 C605[7C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4795 000023A9 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4796 000023AE 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4797                              <1> 
  4798                              <1> AFT_RECAL:
  4799 000023B0 C687[8D6B0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4800 000023B7 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4801 000023B9 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4802                              <1> 
  4803                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4804                              <1> 
  4805 000023BB F687[896B0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4806 000023C2 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4807 000023C4 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4808                              <1> 
  4809 000023C6 3AAF[8D6B0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4810 000023CC 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4811                              <1> 
  4812 000023CE BA[01240000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4813 000023D3 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4814 000023D4 88AF[8D6B0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4815 000023DA B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4816 000023DC E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4817 000023E1 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4818 000023E3 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4819 000023E5 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4820 000023EA 8AA7[8D6B0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4821 000023F0 E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4822 000023F5 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4823                              <1> 
  4824                              <1> ;-----	WAIT FOR HEAD SETTLE
  4825                              <1> 
  4826                              <1> DO_WAIT:
  4827 000023FA 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4828 000023FB E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4829 00002400 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4830                              <1> RB:
  4831                              <1> NEC_ERR:
  4832                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4833                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4834 00002401 C3                  <1> 	RETn				; RETURN TO CALLER
  4835                              <1> 
  4836                              <1> ;-------------------------------------------------------------------------------
  4837                              <1> ; RECAL
  4838                              <1> ;	RECALIBRATE DRIVE
  4839                              <1> ;
  4840                              <1> ; ON ENTRY:	DI = DRIVE #
  4841                              <1> ;
  4842                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4843                              <1> ;-------------------------------------------------------------------------------
  4844                              <1> RECAL:
  4845                              <1> 	;PUSH	CX
  4846                              <1> 	; 24/12/2021
  4847 00002402 51                  <1> 	push	ecx
  4848 00002403 B8[1F240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4849 00002408 50                  <1> 	PUSH	eAX
  4850 00002409 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4851 0000240B E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4852 00002410 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4853 00002412 88DC                <1> 	MOV	AH,BL
  4854 00002414 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4855 00002419 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4856 0000241E 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4857                              <1> RC_BACK:
  4858                              <1> 	;POP	CX
  4859                              <1> 	; 24/12/2021
  4860 0000241F 59                  <1> 	pop	ecx
  4861 00002420 C3                  <1> 	RETn
  4862                              <1> 
  4863                              <1> ;-------------------------------------------------------------------------------
  4864                              <1> ; CHK_STAT_2
  4865                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4866                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4867                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4868                              <1> ;
  4869                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4870                              <1> ;-------------------------------------------------------------------------------
  4871                              <1> CHK_STAT_2:
  4872 00002421 B8[49240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4873 00002426 50                  <1> 	PUSH	eAX
  4874 00002427 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4875 0000242C 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4876 0000242E B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4877 00002430 E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4878 00002435 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4879 0000243A 720C                <1> 	JC	short J34
  4880 0000243C A0[7D6B0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4881 00002441 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4882 00002443 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4883 00002445 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4884 00002447 F8                  <1> 	CLC				; GOOD RETURN
  4885                              <1> J34:
  4886 00002448 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4887                              <1> CS_BACK:
  4888 00002449 C3                  <1> 	RETn
  4889                              <1> J35:
  4890 0000244A 800D[7C6B0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4891 00002451 F9                  <1> 	STC				; ERROR RETURN CODE
  4892 00002452 EBF4                <1> 	JMP	SHORT J34
  4893                              <1> 
  4894                              <1> ;-------------------------------------------------------------------------------
  4895                              <1> ; WAIT_INT
  4896                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4897                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4898                              <1> ;	IF THE DRIVE IS NOT READY.
  4899                              <1> ;
  4900                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4901                              <1> ;-------------------------------------------------------------------------------
  4902                              <1> 
  4903                              <1> ; 17/12/2014
  4904                              <1> ; 2.5 seconds waiting !
  4905                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4906                              <1> ; amount of time to wait for completion interrupt from NEC.
  4907                              <1> 
  4908                              <1> 
  4909                              <1> WAIT_INT:
  4910 00002454 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4911 00002455 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4912                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4913                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4914                              <1> 
  4915                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4916                              <1> 	;
  4917                              <1> 	;WAIT_FOR_MEM:	
  4918                              <1> 	;	Waits for a bit at a specified memory location pointed
  4919                              <1> 	;	to by ES:[DI] to become set.
  4920                              <1> 	;INPUT:
  4921                              <1> 	;	AH=Mask to test with.
  4922                              <1> 	;	ES:[DI] = memory location to watch.
  4923                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4924                              <1> 	;	     (normally 30 microseconds per period.)
  4925                              <1> 
  4926                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4927                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4928                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4929                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4930                              <1> 	; 27/02/2015
  4931 00002456 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4932                              <1> WFMS_CHECK_MEM:
  4933 0000245B F605[796B0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4934 00002462 7516                <1>         jnz     short J37
  4935                              <1> WFMS_HI:
  4936 00002464 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4937 00002466 A810                <1> 	TEST	AL,010H			; transition on memory
  4938 00002468 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4939                              <1> WFMS_LO:
  4940 0000246A E461                <1> 	IN	AL,PORT_B		;SYS1
  4941 0000246C A810                <1> 	TEST	AL,010H
  4942 0000246E 74FA                <1> 	JZ	SHORT WFMS_LO
  4943 00002470 E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4944                              <1> ;WFMS_OUTER_LP:
  4945                              <1> ;;	or	bl, bl			; check outer counter
  4946                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4947                              <1> ;	dec	bl
  4948                              <1> ;	jz	short J36A	
  4949                              <1> ;	jmp	short WFMS_CHECK_MEM
  4950                              <1> 
  4951                              <1> 	;17/12/2014
  4952                              <1> 	;16/12/2014
  4953                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4954                              <1> ;J36:
  4955                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4956                              <1> ;	JNZ	short J37
  4957                              <1> 	;16/12/2014
  4958                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4959                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4960                              <1> 	;JNZ	short J36
  4961                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4962                              <1> ;	jb	short J36
  4963                              <1> 
  4964                              <1> ;WFMS_TIMEOUT:
  4965                              <1> ;J36A:
  4966 00002472 800D[7C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4967 00002479 F9                  <1> 	STC				; ERROR RETURN
  4968                              <1> J37:
  4969 0000247A 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4970 0000247B 8025[796B0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4971 00002482 9D                  <1> 	POPF				; RECOVER CARRY
  4972 00002483 C3                  <1> 	RETn				; GOOD RETURN CODE
  4973                              <1> 
  4974                              <1> ;-------------------------------------------------------------------------------
  4975                              <1> ; RESULTS
  4976                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4977                              <1> ;	FOLLOWING AN INTERRUPT.
  4978                              <1> ;
  4979                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4980                              <1> ;		AX,BX,CX,DX DESTROYED
  4981                              <1> ;-------------------------------------------------------------------------------
  4982                              <1> RESULTS:
  4983 00002484 57                  <1> 	PUSH	eDI
  4984 00002485 BF[7D6B0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4985 0000248A B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4986 0000248C 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4987                              <1> 
  4988                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4989                              <1> 
  4990                              <1> _R10: 
  4991                              <1> 	; 16/12/2014
  4992                              <1> 	; wait for (max) 0.5 seconds
  4993                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4994                              <1> 	;XOR	CX,CX			; COUNTER
  4995                              <1> 
  4996                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4997                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4998                              <1> 	; 27/02/2015
  4999 00002490 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  5000                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  5001                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  5002                              <1> 
  5003                              <1> WFPSR_OUTER_LP:
  5004                              <1> 	;
  5005                              <1> WFPSR_CHECK_PORT:
  5006                              <1> J39:					; WAIT FOR MASTER
  5007 00002495 EC                  <1> 	IN	AL,DX			; GET STATUS
  5008 00002496 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5009 00002498 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5010 0000249A 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  5011                              <1> WFPSR_HI:
  5012 0000249C E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  5013 0000249E A810                <1> 	TEST	AL,010H			; transition on memory
  5014 000024A0 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  5015                              <1> WFPSR_LO:
  5016 000024A2 E461                <1> 	IN	AL, PORT_B		; SYS1
  5017 000024A4 A810                <1> 	TEST	AL,010H
  5018 000024A6 74FA                <1> 	JZ	SHORT WFPSR_LO
  5019 000024A8 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  5020                              <1> 	;; 27/02/2015
  5021                              <1> 	;;dec	bh
  5022                              <1> 	;;jnz	short WFPSR_OUTER_LP
  5023                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  5024                              <1> 
  5025                              <1> 	;;mov	byte [wait_count], 0
  5026                              <1> ;J39:					; WAIT FOR MASTER
  5027                              <1> ;	IN	AL,DX			; GET STATUS
  5028                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5029                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5030                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  5031                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  5032                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  5033                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  5034                              <1> 	;
  5035                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  5036                              <1> 	;;jb	short J39	
  5037                              <1> 
  5038                              <1> ;WFPSR_TIMEOUT:
  5039 000024AA 800D[7C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5040 000024B1 F9                  <1> 	STC				; SET ERROR RETURN
  5041 000024B2 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5042                              <1> 
  5043                              <1> ;-----	READ IN THE STATUS
  5044                              <1> 
  5045                              <1> J42:
  5046 000024B4 EB00                <1> 	JMP	$+2			; I/O DELAY
  5047 000024B6 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5048 000024B8 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5049                              <1> 	; 16/12/2014
  5050                              <1> 	NEWIODELAY
  2146 000024B9 E6EB                <2>  out 0EBh,al
  5051 000024BB 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5052 000024BD 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5053                              <1> 	; 16/12/2014
  5054                              <1> ;	push	cx
  5055                              <1> ;	mov	cx, 30
  5056                              <1> ;wdw2:
  5057                              <1> ;	NEWIODELAY
  5058                              <1> ;	loop	wdw2
  5059                              <1> ;	pop	cx
  5060                              <1> 
  5061 000024BE B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5062 000024C3 E8F6EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5063 000024C8 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5064 000024CA EC                  <1> 	IN	AL,DX			; GET STATUS
  5065                              <1> 	; 16/12/2014
  5066                              <1> 	NEWIODELAY
  2146 000024CB E6EB                <2>  out 0EBh,al
  5067                              <1> 	;
  5068 000024CD A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5069 000024CF 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5070                              <1> 
  5071 000024D1 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5072 000024D3 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5073 000024D5 800D[7C6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5074 000024DC F9                  <1> 	STC				; SET ERROR FLAG
  5075                              <1> 
  5076                              <1> ;-----	RESULT OPERATION IS DONE
  5077                              <1> POPRES:
  5078 000024DD 5F                  <1> 	POP	eDI
  5079 000024DE C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5080                              <1> 
  5081                              <1> ;-------------------------------------------------------------------------------
  5082                              <1> ; READ_DSKCHNG
  5083                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5084                              <1> ;
  5085                              <1> ; ON ENTRY:	DI = DRIVE #
  5086                              <1> ;
  5087                              <1> ; ON EXIT:	DI = DRIVE #
  5088                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5089                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5090                              <1> ;		AX,CX,DX DESTROYED
  5091                              <1> ;-------------------------------------------------------------------------------
  5092                              <1> READ_DSKCHNG:
  5093 000024DF E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5094 000024E4 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5095 000024E8 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5096 000024E9 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5097 000024EB C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5098                              <1> 
  5099                              <1> ;-------------------------------------------------------------------------------
  5100                              <1> ; DRIVE_DET
  5101                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5102                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5103                              <1> ; ON ENTRY:	DI = DRIVE #
  5104                              <1> ;-------------------------------------------------------------------------------
  5105                              <1> DRIVE_DET:
  5106 000024EC E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5107 000024F1 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5108 000024F6 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5109 000024F8 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5110 000024FA E884FEFFFF          <1> 	CALL	SEEK
  5111 000024FF 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5112 00002501 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5113                              <1> SK_GIN:
  5114 00002503 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5115                              <1> 	;PUSH	CX			; SAVE TRACK
  5116                              <1> 	; 24/12/2021
  5117 00002505 51                  <1> 	push	ecx
  5118 00002506 E878FEFFFF          <1> 	CALL	SEEK
  5119 0000250B 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5120 0000250D B8[48250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5121 00002512 50                  <1> 	PUSH	eAX
  5122 00002513 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5123 00002515 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5124 0000251A 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5125 0000251D 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5126 0000251F E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5127 00002524 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5128 00002529 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5129                              <1> 	;POP	CX			; RESTORE TRACK
  5130                              <1> 	; 24/12/2021
  5131 0000252A 59                  <1> 	pop	ecx
  5132 0000252B F605[7D6B0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5133 00002532 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5134 00002534 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5135 00002536 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5136                              <1> 
  5137                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5138                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5139                              <1> 
  5140 00002538 808F[896B0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5141 0000253F C3                  <1> 	RETn				; ALL INFORMATION SET
  5142                              <1> IS_80:
  5143 00002540 808F[896B0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5144                              <1> DD_BAC:
  5145 00002547 C3                  <1> 	RETn
  5146                              <1> POP_BAC:
  5147                              <1> 	;POP	CX			; THROW AWAY
  5148                              <1> 	; 24/12/2021
  5149 00002548 59                  <1> 	pop	ecx
  5150 00002549 C3                  <1> 	RETn
  5151                              <1> 
  5152                              <1> fdc_int:  
  5153                              <1> 	  ; 30/07/2015	
  5154                              <1> 	  ; 16/02/2015
  5155                              <1> ;int_0Eh: ; 11/12/2014
  5156                              <1> 
  5157                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5158                              <1> ; DISK_INT
  5159                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5160                              <1> ;
  5161                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5162                              <1> ;-------------------------------------------------------------------------------
  5163                              <1> DISK_INT_1:
  5164                              <1> 
  5165                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5166                              <1> 	; 24/12/2021
  5167 0000254A 50                  <1> 	push	eax
  5168 0000254B 1E                  <1> 	push	ds
  5169 0000254C 66B81000            <1> 	mov	ax, KDATA
  5170 00002550 8ED8                <1> 	mov 	ds, ax
  5171 00002552 800D[796B0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5172 00002559 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5173 0000255B E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5174 0000255D 1F                  <1> 	pop	ds
  5175                              <1> 	;POP	AX			; RECOVER REGISTER
  5176                              <1> 	; 24/12/2021
  5177 0000255E 58                  <1> 	pop	eax
  5178 0000255F CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5179                              <1> 
  5180                              <1> ;-------------------------------------------------------------------------------
  5181                              <1> ; DSKETTE_SETUP
  5182                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5183                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5184                              <1> ;-------------------------------------------------------------------------------
  5185                              <1> DSKETTE_SETUP:
  5186                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5187                              <1> 	;PUSH	BX
  5188                              <1> 	;PUSH	CX
  5189 00002560 52                  <1> 	PUSH	eDX
  5190                              <1> 	;PUSH	DI
  5191                              <1> 	;;PUSH	DS
  5192                              <1> 	; 14/12/2014
  5193                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5194                              <1> 	;mov	[DISK_POINTER+2], cs
  5195                              <1> 	;
  5196                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5197 00002561 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5198 00002563 66C705[896B0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5198 0000256B 00                  <1>
  5199 0000256C 8025[846B0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5200 00002573 800D[846B0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5201 0000257A C605[796B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5202 00002581 C605[7B6B0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5203 00002588 C605[7A6B0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5204 0000258F C605[7C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5205                              <1> 	;
  5206                              <1> 	; 28/02/2015
  5207                              <1> 	;mov	word [cfd], 100h 
  5208 00002596 E89DF2FFFF          <1> 	call	DSK_RESET
  5209 0000259B 5A                  <1> 	pop	edx
  5210 0000259C C3                  <1> 	retn
  5211                              <1> 
  5212                              <1> ;SUP0:
  5213                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5214                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5215                              <1> ;	; 02/01/2015
  5216                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5217                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5218                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5219                              <1> ;       cmp     byte [fd1_type], 0	
  5220                              <1> ;	jna	short sup1
  5221                              <1> ;	or	di, di
  5222                              <1> ;	jnz	short sup1
  5223                              <1> ;	inc	di
  5224                              <1> ;       jmp     short SUP0
  5225                              <1> ;sup1:
  5226                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5227                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5228                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5229                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5230                              <1> ;	;POP	DI
  5231                              <1> ;	POP	eDX
  5232                              <1> ;	;POP	CX
  5233                              <1> ;	;POP	BX
  5234                              <1> ;	;POP	AX
  5235                              <1> ;	RETn
  5236                              <1> 
  5237                              <1> ;//////////////////////////////////////////////////////
  5238                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5239                              <1> ;
  5240                              <1> 
  5241                              <1> int13h: ; 21/02/2015
  5242 0000259D 9C                  <1> 	pushfd
  5243 0000259E 0E                  <1> 	push 	cs
  5244 0000259F E859000000          <1> 	call 	DISK_IO
  5245 000025A4 C3                  <1> 	retn
  5246                              <1> 
  5247                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5248                              <1> ;/////////////////////////////////////////////////////////////////////
  5249                              <1> 
  5250                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5251                              <1> ; 23/02/2015
  5252                              <1> ; 21/02/2015 (unix386.s)
  5253                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5254                              <1> ;
  5255                              <1> ; Original Source Code:
  5256                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5257                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5258                              <1> ;
  5259                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5260                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5261                              <1> ;
  5262                              <1> 
  5263                              <1> ;The wait for controller to be not busy is 10 seconds.
  5264                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5265                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5266                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5267                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5268                              <1> 
  5269                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5270                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5271                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5272                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5273                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5274                              <1> 
  5275                              <1> ;The wait for Data request on read and write longs is
  5276                              <1> ;2000 us. (?)
  5277                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5278                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5279                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5280                              <1> 
  5281                              <1> ; Port 61h (PORT_B)
  5282                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5283                              <1> 
  5284                              <1> ; 23/12/2014
  5285                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5286                              <1> 
  5287                              <1> ;--- INT 13H -------------------------------------------------------------------
  5288                              <1> ;									       :
  5289                              <1> ; FIXED DISK I/O INTERFACE						       :
  5290                              <1> ;									       :
  5291                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5292                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5293                              <1> ;									       :
  5294                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5295                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5296                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5297                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5298                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5299                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5300                              <1> ;									       :
  5301                              <1> ;------------------------------------------------------------------------------:
  5302                              <1> ;									       :
  5303                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5304                              <1> ;									       :
  5305                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5306                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5307                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5308                              <1> ;			  DL > 80H - DISK				       :
  5309                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5310                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5311                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5312                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5313                              <1> ;	(AH)= 06H  UNUSED						       :
  5314                              <1> ;	(AH)= 07H  UNUSED						       :
  5315                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5316                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5317                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5318                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5319                              <1> ;	(AH)= 0AH  READ LONG						       :
  5320                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5321                              <1> ;	(AH)= 0CH  SEEK 						       :
  5322                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5323                              <1> ;	(AH)= 0EH  UNUSED						       :
  5324                              <1> ;	(AH)= 0FH  UNUSED						       :
  5325                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5326                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5327                              <1> ;	(AH)= 12H  UNUSED						       :
  5328                              <1> ;	(AH)= 13H  UNUSED						       :
  5329                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5330                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5331                              <1> ;									       :
  5332                              <1> ;-------------------------------------------------------------------------------
  5333                              <1> ;									       :
  5334                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5335                              <1> ;									       :
  5336                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5337                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5338                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5339                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5340                              <1> ;									       :
  5341                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5342                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5343                              <1> ;				 (10 BITS TOTAL)			       :
  5344                              <1> ;									       :
  5345                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5346                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5347                              <1> ;									       :
  5348                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5349                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5350                              <1> ;									       :
  5351                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5352                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5353                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5354                              <1> ;			       80H FOR A BAD SECTOR			       :
  5355                              <1> ;			   N = SECTOR NUMBER				       :
  5356                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5357                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5358                              <1> ;									       :
  5359                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5360                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5361                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5362                              <1> ;									       :
  5363                              <1> ;-------------------------------------------------------------------------------
  5364                              <1> 
  5365                              <1> ;-------------------------------------------------------------------------------
  5366                              <1> ; OUTPUT								       :
  5367                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5368                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5369                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5370                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5371                              <1> ;									       :
  5372                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5373                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5374                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5375                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5376                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5377                              <1> ;		REWRITTEN.						       :
  5378                              <1> ;									       :
  5379                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5380                              <1> ;	   INPUT:							       :
  5381                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5382                              <1> ;	   OUTPUT:							       :
  5383                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5384                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5385                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5386                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5387                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5388                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5389                              <1> ;									       :
  5390                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5391                              <1> ;									       :
  5392                              <1> ;	AH = 0 - NOT PRESENT						       :
  5393                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5394                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5395                              <1> ;	     3 - FIXED DISK						       :
  5396                              <1> ;									       :
  5397                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5398                              <1> ;									       :
  5399                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5400                              <1> ;	INFORMATION.							       :
  5401                              <1> ;									       :
  5402                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5403                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5404                              <1> ;									       :
  5405                              <1> ;-------------------------------------------------------------------------------
  5406                              <1> 
  5407                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5408                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5409                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5410                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5411                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5412                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5413                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5414                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5415                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5416                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5417                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5418                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5419                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5420                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5421                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5422                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5423                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5424                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5425                              <1> 
  5426                              <1> ;--------------------------------------------------------
  5427                              <1> ;							:
  5428                              <1> ; FIXED DISK PARAMETER TABLE				:
  5429                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5430                              <1> ;							:
  5431                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5432                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5433                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5434                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5435                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5436                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5437                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5438                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5439                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5440                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5441                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5442                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5443                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5444                              <1> ;							:
  5445                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5446                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5447                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5448                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5449                              <1> ;							:
  5450                              <1> ;--------------------------------------------------------
  5451                              <1> 
  5452                              <1> ;--------------------------------------------------------
  5453                              <1> ;							:
  5454                              <1> ; HARDWARE SPECIFIC VALUES				:
  5455                              <1> ;							:
  5456                              <1> ;  -  CONTROLLER I/O PORT				:
  5457                              <1> ;							:
  5458                              <1> ;     > WHEN READ FROM: 				:
  5459                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5460                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5461                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5462                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5463                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5464                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5465                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5466                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5467                              <1> ;							:
  5468                              <1> ;     > WHEN WRITTEN TO:				:
  5469                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5470                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5471                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5472                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5473                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5474                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5475                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5476                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5477                              <1> ;							:
  5478                              <1> ;--------------------------------------------------------
  5479                              <1> 
  5480                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5481                              <1> ;HF1_PORT	equ	0170h	
  5482                              <1> ;HF_REG_PORT	EQU	03F6H
  5483                              <1> ;HF1_REG_PORT	equ	0376h
  5484                              <1> 
  5485                              <1> HDC1_BASEPORT	equ	1F0h
  5486                              <1> HDC2_BASEPORT	equ	170h		
  5487                              <1> 
  5488 000025A5 90                  <1> align 2
  5489                              <1> 
  5490                              <1> ;-----		STATUS REGISTER
  5491                              <1> 
  5492                              <1> ST_ERROR	EQU	00000001B	;
  5493                              <1> ST_INDEX	EQU	00000010B	;
  5494                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5495                              <1> ST_DRQ		EQU	00001000B	;
  5496                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5497                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5498                              <1> ST_READY	EQU	01000000B	;
  5499                              <1> ST_BUSY 	EQU	10000000B	;
  5500                              <1> 
  5501                              <1> ;-----		ERROR REGISTER
  5502                              <1> 
  5503                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5504                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5505                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5506                              <1> ;		EQU	00001000B	; NOT USED
  5507                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5508                              <1> ;		EQU	00100000B	; NOT USED
  5509                              <1> ERR_DATA_ECC	EQU	01000000B
  5510                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5511                              <1> 
  5512                              <1> 
  5513                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5514                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5515                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5516                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5517                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5518                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5519                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5520                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5521                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5522                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5523                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5524                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5525                              <1> 
  5526                              <1> ;MAX_FILE	EQU	2
  5527                              <1> ;S_MAX_FILE	EQU	2
  5528                              <1> MAX_FILE	equ	4		; 22/12/2014
  5529                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5530                              <1> 
  5531                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5532                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5533                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5534                              <1> 
  5535                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5536                              <1> 
  5537                              <1> ;-----		COMMAND BLOCK REFERENCE
  5538                              <1> 
  5539                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5540                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5541                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5542                              <1> ; 19/12/2014
  5543                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5544                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5545                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5546                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5547                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5548                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5549                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5550                              <1> 
  5551                              <1> align 2
  5552                              <1> 
  5553                              <1> ;----------------------------------------------------------------
  5554                              <1> ; FIXED DISK I/O SETUP						:
  5555                              <1> ;								:
  5556                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5557                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5558                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5559                              <1> ;								:
  5560                              <1> ;----------------------------------------------------------------
  5561                              <1> 
  5562                              <1> DISK_SETUP:
  5563                              <1> 	;CLI
  5564                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5565                              <1> 	;xor	ax,ax
  5566                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5567                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5568                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5569                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5570                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5571                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5572                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5573                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5574                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5575                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5576                              <1> 	;;MOV	[HDISK_INT+2],CS
  5577                              <1> 	;mov	[HDISK_INT1+2],CS
  5578                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5579                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5580                              <1> 	;mov	[HDISK_INT2+2],CS
  5581                              <1> 	;
  5582                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5583                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5584                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5585                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5586                              <1> 	;push	cs
  5587                              <1> 	;pop	ds
  5588                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5589                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5590 000025A6 C705[946B0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5590 000025AE 0900                <1>
  5591                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5592                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5593 000025B0 C705[986B0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5593 000025B8 0900                <1>
  5594                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5595                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5596 000025BA C705[9C6B0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5596 000025C2 0900                <1>
  5597                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5598                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5599 000025C4 C705[A06B0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5599 000025CC 0900                <1>
  5600                              <1> 	;
  5601                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5602                              <1> 	;;;AND	AL,0BFH
  5603                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5604                              <1> 	;;;JMP	$+2
  5605                              <1> 	;;IODELAY
  5606                              <1> 	;;OUT	INTB01,AL
  5607                              <1> 	;;IODELAY
  5608                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5609                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5610                              <1> 	;;;JMP	$+2
  5611                              <1> 	;;IODELAY
  5612                              <1> 	;;OUT	INTA01,AL
  5613                              <1> 	;
  5614                              <1> 	;STI
  5615                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5616                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5617                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5618                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5619                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5620                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5621                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5622                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5623                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5624                              <1> 	;mov	si, hd0_type
  5625 000025CE BE[F0650000]        <1> 	mov	esi, hd0_type
  5626                              <1> 	;mov	cx, 4
  5627 000025D3 B904000000          <1> 	mov	ecx, 4
  5628                              <1> hde_l:
  5629 000025D8 AC                  <1> 	lodsb
  5630 000025D9 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5631 000025DB 7206                <1> 	jb	short _L4
  5632 000025DD FE05[906B0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5633                              <1> _L4: ; 26/02/2015
  5634 000025E3 E2F3                <1> 	loop	hde_l	
  5635                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5636                              <1> ;L4:
  5637                              <1> 	; 
  5638                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5639                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5640                              <1> 	;;mov 	cl, 3
  5641                              <1> 	;;
  5642                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5643                              <1> ;;hdc_dl:
  5644                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5645                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5646                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5647                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5648                              <1> 	;;jnc	short hdc_reset0
  5649                              <1> 	;;loop	hdc_dl
  5650                              <1> 	;;; 27/12/2014
  5651                              <1> 	;;stc
  5652                              <1> 	;;retn
  5653                              <1> 	;
  5654                              <1> ;;hdc_reset0:
  5655                              <1> 	; 18/01/2015
  5656 000025E5 8A0D[906B0000]      <1> 	mov	cl, [HF_NUM]
  5657 000025EB 20C9                <1> 	and	cl, cl
  5658 000025ED 740D                <1> 	jz	short POD_DONE
  5659                              <1> 	;
  5660 000025EF B27F                <1> 	mov	dl, 7Fh
  5661                              <1> hdc_reset1:
  5662 000025F1 FEC2                <1> 	inc	dl
  5663                              <1> 	;; 31/12/2015
  5664                              <1> 	;;push	dx
  5665                              <1> 	;;push	cx
  5666                              <1> 	;;push	ds
  5667                              <1> 	;;sub	ax, ax
  5668                              <1> 	;;mov	ds, ax
  5669                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5670                              <1> 	;;pop	ds
  5671                              <1> 	;;MOV	BX,AX
  5672                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5673                              <1> 	;;MOV	CX,AX
  5674                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5675                              <1> 	;;
  5676                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5677                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5678                              <1> 	;;pop	cx
  5679                              <1> 	;;pop	dx
  5680                              <1> 	;;
  5681                              <1> 	; 18/01/2015
  5682 000025F3 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5683                              <1> 	;int	13h
  5684 000025F5 E8A3FFFFFF          <1> 	call	int13h
  5685 000025FA E2F5                <1> 	loop	hdc_reset1
  5686                              <1> POD_DONE:
  5687 000025FC C3                  <1> 	RETn
  5688                              <1> 
  5689                              <1> ;;-----	POD_ERROR
  5690                              <1> 
  5691                              <1> ;;CTL_ERRX:
  5692                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5693                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5694                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5695                              <1> ;	;JMP	short POD_DONE
  5696                              <1> 
  5697                              <1> ;;HD_RESET_1:
  5698                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5699                              <1> ;;	;PUSH	CX
  5700                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5701                              <1> ;;	INT	13H
  5702                              <1> ;;	JC	short RES_2
  5703                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5704                              <1> ;;	INT	13H
  5705                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5706                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5707                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5708                              <1> ;;					; (30 seconds)		
  5709                              <1> ;;	;cmc
  5710                              <1> ;;	;JNC	short RES_1
  5711                              <1> ;;	jb	short RES_1
  5712                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5713                              <1> ;;	;TEST	DL,1
  5714                              <1> ;;	;JNZ	RES_E1
  5715                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5716                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5717                              <1> ;;	;JMP	SHORT RES_E1
  5718                              <1> ;;RES_ER: ; 22/12/2014
  5719                              <1> ;;RES_OK:
  5720                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5721                              <1> ;;	;POP	BX
  5722                              <1> ;;	RETn
  5723                              <1> ;;
  5724                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5725                              <1> ;;	INT	13H
  5726                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5727                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5728                              <1> ;;	INT	13H
  5729                              <1> ;;	JC	short RES_ER
  5730                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5731                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5732                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5733                              <1> ;;	INT	13H
  5734                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5735                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5736                              <1> ;;	JE	short RES_OK
  5737                              <1> ;;	CMP	AH,DATA_CORRECTED
  5738                              <1> ;;	JE	short RES_OK
  5739                              <1> ;;	CMP	AH,BAD_ECC
  5740                              <1> ;;	JE	short RES_OK
  5741                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5742                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5743                              <1> ;;					; (60 seconds)		
  5744                              <1> ;;	cmc
  5745                              <1> ;;	JC	short RES_ER		; FAILED
  5746                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5747                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5748                              <1> ;;	AND	AL,3FH
  5749                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5750                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5751                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5752                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5753                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5754                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5755                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5756                              <1> ;;	;TEST	DL,1
  5757                              <1> ;;	;JNZ	short RES_E1
  5758                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5759                              <1> ;;;RES_E1:
  5760                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5761                              <1> ;;;RES_OK:
  5762                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5763                              <1> ;;	;POP	BX
  5764                              <1> ;;	;RETn
  5765                              <1> ;
  5766                              <1> ;;SET_FAIL:
  5767                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5768                              <1> ;	;CALL	CMOS_READ
  5769                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5770                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5771                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5772                              <1> ;	;RETn
  5773                              <1> ;
  5774                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5775                              <1> ;	;POP	AX			; SAVE RETURN
  5776                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5777                              <1> ;	;POP	BX
  5778                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5779                              <1> ;	;PUSH	CX
  5780                              <1> ;	;PUSH	AX
  5781                              <1> ;	;push	ds
  5782                              <1> ;	;xor	ax, ax
  5783                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5784                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5785                              <1> ;	;				; BX = START TIME
  5786                              <1> ;	;				; CX = END TIME
  5787                              <1> ;	;pop	ds
  5788                              <1> ;	;CMP	BX,CX
  5789                              <1> ;	;JB	short TCHK1		; START < END
  5790                              <1> ;	;CMP	BX,AX
  5791                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5792                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5793                              <1> ;;TCHK1: CMP	AX,BX
  5794                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5795                              <1> ;;TCHK2: CMP	AX,CX
  5796                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5797                              <1> ;;					; OR CURRENT < END < START
  5798                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5799                              <1> ;;	RETn
  5800                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5801                              <1> ;;	RETn
  5802                              <1> ;;
  5803                              <1> ;;int_13h:
  5804                              <1> 
  5805                              <1> ;----------------------------------------
  5806                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5807                              <1> ;----------------------------------------
  5808                              <1> 
  5809                              <1> DISK_IO:
  5810 000025FD 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5811                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5812                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5813                              <1> 	;;call	int40h
  5814                              <1> 	;jb	DISKETTE_IO_1
  5815                              <1> 	; 24/12/2021
  5816 00002600 7305                <1> 	jnb	short A1
  5817 00002602 E95FF1FFFF          <1> 	jmp	DISKETTE_IO_1
  5818                              <1> ;RET_2:
  5819                              <1> 	;RETf	2			; BACK TO CALLER
  5820                              <1> ;	retf	4
  5821                              <1> A1:
  5822 00002607 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5823                              <1> 	;; 04/01/2015
  5824                              <1> 	;;OR	AH,AH
  5825                              <1> 	;;JNZ	short A2
  5826                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5827                              <1> 	;;SUB	AH,AH
  5828 00002608 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5829 0000260B 772E                <1> 	JA	short RET_2
  5830                              <1> 	; 18/01/2015
  5831 0000260D 08E4                <1> 	or	ah,ah
  5832 0000260F 742D                <1> 	jz	short A4
  5833 00002611 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5834 00002614 7504                <1> 	jne	short A2
  5835 00002616 28E4                <1> 	sub	ah,ah	; Reset
  5836 00002618 EB24                <1> 	jmp	short A4
  5837                              <1> A2:
  5838 0000261A 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5839                              <1> 	;JNZ	short A3
  5840                              <1>         ;JMP    GET_PARM_N
  5841                              <1> 	;je	GET_PARM_N
  5842                              <1> 	; 24/12/2021
  5843 0000261D 7505                <1> 	jne	short A3
  5844 0000261F E90D030000          <1> 	jmp	GET_PARM_N
  5845                              <1> A3:	
  5846 00002624 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5847                              <1> 	;JNZ	short A4
  5848                              <1>         ;JMP    READ_DASD_TYPE
  5849                              <1> 	;je	READ_DASD_TYPE
  5850                              <1> 	; 24/12/2021
  5851 00002627 7505                <1> 	jne	short A3_A4
  5852 00002629 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5853                              <1> A3_A4:
  5854                              <1> 	; 02/02/2015
  5855 0000262E 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5856                              <1> 	; 12/01/2015
  5857 00002631 F5                  <1> 	cmc
  5858 00002632 730A                <1> 	jnc	short A4
  5859                              <1> 	; 30/01/2015
  5860                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5861 00002634 C605[8F6B0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5862                              <1> 	;jmp	short RET_2
  5863                              <1> RET_2:
  5864 0000263B CA0400              <1> 	retf	4
  5865                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5866 0000263E C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5867 00002642 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5868 00002643 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5869 00002644 52                  <1> 	PUSH	eDX
  5870 00002645 1E                  <1> 	PUSH	DS
  5871 00002646 06                  <1> 	PUSH	ES
  5872 00002647 56                  <1> 	PUSH	eSI
  5873 00002648 57                  <1> 	PUSH	eDI
  5874                              <1> 	;;04/01/2015
  5875                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5876                              <1> 	;;JNZ	short A5
  5877                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5878                              <1> ;;A5:	
  5879                              <1> 	;push	cs
  5880                              <1> 	;pop	ds
  5881                              <1> 	; 21/02/2015
  5882                              <1> 	;push	ax
  5883                              <1> 	; 24/12/2021
  5884 00002649 50                  <1> 	push	eax
  5885 0000264A 66B81000            <1> 	mov	ax, KDATA
  5886 0000264E 8ED8                <1> 	mov	ds, ax
  5887 00002650 8EC0                <1> 	mov	es, ax	
  5888                              <1> 	;pop	ax
  5889                              <1> 	; 24/12/2021
  5890 00002652 58                  <1> 	pop	eax
  5891 00002653 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5892                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5893 00002658 8A25[8F6B0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5894 0000265E 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5895 00002661 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5896 00002662 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5897 00002663 5E                  <1> 	POP	eSI
  5898 00002664 07                  <1>         POP     ES
  5899 00002665 1F                  <1>         POP     DS
  5900 00002666 5A                  <1> 	POP	eDX
  5901 00002667 59                  <1> 	POP	eCX
  5902 00002668 5B                  <1> 	POP	eBX
  5903 00002669 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5904                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5905 0000266A CA0400              <1> 	retf	4
  5906                              <1> ; 21/02/2015
  5907                              <1> ;       dw --> dd
  5908                              <1> M1:					; FUNCTION TRANSFER TABLE
  5909 0000266D [26280000]          <1> 	dd	DISK_RESET		; 000H
  5910 00002671 [9B280000]          <1> 	dd	RETURN_STATUS		; 001H
  5911 00002675 [A8280000]          <1> 	dd	DISK_READ		; 002H
  5912 00002679 [B1280000]          <1> 	dd	DISK_WRITE		; 003H
  5913 0000267D [BA280000]          <1> 	dd	DISK_VERF		; 004H
  5914 00002681 [D2280000]          <1> 	dd	FMT_TRK 		; 005H
  5915 00002685 [1C280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5916 00002689 [1C280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5917 0000268D [1C280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5918 00002691 [93290000]          <1> 	dd	INIT_DRV		; 009H
  5919 00002695 [F2290000]          <1> 	dd	RD_LONG 		; 00AH
  5920 00002699 [FB290000]          <1> 	dd	WR_LONG 		; 00BH
  5921 0000269D [042A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5922 000026A1 [26280000]          <1> 	dd	DISK_RESET		; 00DH
  5923 000026A5 [1C280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5924 000026A9 [1C280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5925 000026AD [2C2A0000]          <1> 	dd	TST_RDY 		; 010H
  5926 000026B1 [502A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5927 000026B5 [1C280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5928 000026B9 [1C280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5929 000026BD [862A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5930                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5931 000026C1 [1C280000]          <1> 	dd	BAD_COMMAND		; 015h
  5932 000026C5 [1C280000]          <1> 	dd	BAD_COMMAND		; 016h
  5933 000026C9 [1C280000]          <1> 	dd	BAD_COMMAND		; 017h
  5934 000026CD [1C280000]          <1> 	dd	BAD_COMMAND		; 018h
  5935 000026D1 [1C280000]          <1> 	dd	BAD_COMMAND		; 019h
  5936 000026D5 [1C280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5937 000026D9 [A8280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5938 000026DD [B1280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5939                              <1> M1L     EQU    $-M1
  5940                              <1> 
  5941                              <1> DISK_IO_CONT:
  5942                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5943 000026E1 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5944                              <1> 	;;JNZ	short SU0
  5945                              <1>         ;;JMP	RETURN_STATUS
  5946                              <1> 	;je	RETURN_STATUS
  5947                              <1> 	; 24/12/2021
  5948 000026E4 7505                <1> 	jne	short SU0
  5949 000026E6 E9B0010000          <1> 	jmp	RETURN_STATUS
  5950                              <1> SU0:
  5951 000026EB C605[8F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5952                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5953                              <1> 	;mov	si, bx ;; 14/02/2015
  5954 000026F2 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5955 000026F4 8A1D[906B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5956                              <1> 	;; 04/01/2015
  5957                              <1> 	;;PUSH	AX
  5958 000026FA 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5959                              <1> 					; (get drive number as 0 to 3)
  5960 000026FD 38D3                <1> 	CMP	BL,DL
  5961                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5962                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5963                              <1> 	; 24/12/2021
  5964 000026FF 7705                <1> 	ja	short su0_su1
  5965 00002701 E916010000          <1> 	jmp	BAD_COMMAND
  5966                              <1> su0_su1:
  5967                              <1>         ;;03/01/2015
  5968 00002706 29DB                <1> 	sub	ebx, ebx
  5969 00002708 88D3                <1> 	mov	bl, dl
  5970                              <1> 	;sub	bh, bh
  5971 0000270A 883D[A46B0000]      <1> 	mov	[LBAMode], bh 	; 0
  5972                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5973                              <1> 	;test	byte [ebx+hd0_type], 1
  5974                              <1> 	;jz	short su1		; no
  5975                              <1> 	;inc	byte [LBAMode]
  5976                              <1> ;su1:
  5977                              <1> 	; 21/02/2015 (32 bit modification)
  5978                              <1> 	; 04/01/2015
  5979                              <1> 	;push	ax ; ***
  5980                              <1> 	; 24/12/2021
  5981 00002710 50                  <1> 	push	eax ; ***
  5982                              <1> 	;PUSH	ES ; **
  5983                              <1> 	;PUSH	DX ; *
  5984                              <1> 	; 24/12/2021
  5985 00002711 52                  <1> 	push	edx ; *
  5986                              <1> 	;push	ax
  5987 00002712 50                  <1> 	push	eax
  5988 00002713 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5989                              <1> 	; 02/02/2015
  5990                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5991 00002718 668B4310            <1> 	mov	ax, [ebx+16]
  5992 0000271C 66A3[E4650000]      <1> 	mov	[HF_PORT], ax
  5993                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5994 00002722 668B5312            <1> 	mov	dx, [ebx+18]
  5995 00002726 668915[E6650000]    <1> 	mov	[HF_REG_PORT], dx
  5996                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5997 0000272D 8A4314              <1> 	mov	al, [ebx+20]
  5998                              <1> 	; 23/02/2015
  5999 00002730 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  6000 00002732 7406                <1> 	jz 	short su1
  6001 00002734 FE05[A46B0000]      <1> 	inc	byte [LBAMode] ; 1 
  6002                              <1> su1: 	 
  6003 0000273A C0E804              <1> 	shr 	al, 4
  6004 0000273D 2401                <1> 	and	al, 1			
  6005 0000273F A2[E8650000]        <1> 	mov	[hf_m_s], al 
  6006                              <1> 	;
  6007                              <1> 	; 03/01/2015
  6008                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  6009 00002744 8A4308              <1> 	mov	al, [ebx+8]
  6010                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  6011 00002747 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  6012                              <1> 					; Control Byte:  (= 08h, here)
  6013                              <1> 					; bit 0 - 0
  6014                              <1> 					; bit 1 - nIEN (1 = disable irq)
  6015                              <1> 					; bit 2 - SRST (software RESET)
  6016                              <1> 					; bit 3 - use extra heads (8 to 15)
  6017                              <1> 					;         -always set to 1-	
  6018                              <1> 					; (bits 3 to 7 are reserved
  6019                              <1> 					;          for ATA devices)
  6020 00002748 8A25[916B0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6021 0000274E 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  6022 00002751 08C4                <1> 	OR	AH,AL
  6023 00002753 8825[916B0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  6024                              <1> 	; 04/01/2015
  6025                              <1> 	;pop	ax
  6026                              <1> 	; 24/12/2021
  6027 00002759 58                  <1> 	pop	eax
  6028                              <1> 	;pop	dx ; * ;; 14/02/2015
  6029                              <1> 	; 24/12/2021
  6030 0000275A 5A                  <1> 	pop	edx ; *
  6031 0000275B 20E4                <1> 	and	ah, ah	; Reset function ?
  6032 0000275D 7506                <1> 	jnz	short su2
  6033                              <1> 	;;pop	dx ; * ;; 14/02/2015
  6034                              <1> 	;pop	es ; **
  6035                              <1> 	;pop	ax ; ***
  6036                              <1> 	; 24/12/2021
  6037 0000275F 58                  <1> 	pop	eax ; ***	
  6038                              <1> 	;;pop	bx
  6039 00002760 E9C1000000          <1>         jmp     DISK_RESET
  6040                              <1> su2:
  6041 00002765 803D[A46B0000]00    <1> 	cmp	byte [LBAMode], 0
  6042 0000276C 765E                <1> 	jna	short su3
  6043                              <1> 	;
  6044                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6045 0000276E 80FC1B              <1> 	cmp	ah, 1Bh
  6046 00002771 720B                <1> 	jb	short lbarw1
  6047 00002773 80FC1C              <1> 	cmp	ah, 1Ch
  6048 00002776 7759                <1> 	ja 	short invldfnc
  6049                              <1> 	;;pop	dx ; * ; 14/02/2015
  6050                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6051 00002778 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6052                              <1> 	;; 14/02/2015
  6053 0000277A 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6054                              <1> 	;;mov	dx, bx
  6055                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6056                              <1> 	;;mov	bx, di
  6057                              <1> 	;mov	si, di ; Buffer offset
  6058 0000277C EB2E                <1> 	jmp	short lbarw2
  6059                              <1> lbarw1:
  6060                              <1> 	; convert CHS to LBA
  6061                              <1> 	;
  6062                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6063                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6064                              <1> 	;	+ Sector - 1
  6065                              <1> 	;push	dx ; * ;; 14/02/2015
  6066                              <1> 	; 24/12/2021
  6067 0000277E 52                  <1> 	push	edx ; *
  6068                              <1> 	;xor	dh, dh
  6069 0000277F 31D2                <1> 	xor	edx, edx
  6070                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6071 00002781 8A530E              <1> 	mov	dl, [ebx+14]
  6072                              <1> 	;xor	ah, ah
  6073 00002784 31C0                <1> 	xor	eax, eax
  6074                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6075 00002786 8A4302              <1> 	mov	al, [ebx+2]
  6076 00002789 FEC8                <1> 	dec	al
  6077                              <1> 	;inc	ax		; 0 =  256
  6078 0000278B 40                  <1> 	inc	eax ; 24/12/2021
  6079 0000278C 66F7E2              <1> 	mul 	dx
  6080                              <1> 		; AX = # of Heads" * Sectors/Track
  6081 0000278F 6689CA              <1> 	mov	dx, cx
  6082                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6083 00002792 83E13F              <1> 	and	ecx, 3fh
  6084 00002795 86D6                <1> 	xchg	dl, dh
  6085 00002797 C0EE06              <1> 	shr	dh, 6
  6086                              <1> 		; DX = cylinder (0 to 1023)
  6087                              <1> 	;mul 	dx
  6088                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6089 0000279A F7E2                <1> 	mul	edx
  6090 0000279C FEC9                <1> 	dec	cl  ; sector - 1
  6091                              <1> 	;add	ax, cx
  6092                              <1> 	;adc	dx, 0
  6093                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6094 0000279E 01C8                <1> 	add	eax, ecx
  6095                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6096                              <1> 	; 24/12/2021
  6097 000027A0 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6098                              <1> 	;push	dx
  6099                              <1> 	;push	ax
  6100 000027A1 50                  <1> 	push	eax
  6101                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6102 000027A2 8A430E              <1> 	mov	al, [ebx+14]
  6103 000027A5 F6E5                <1> 	mul	ch
  6104                              <1> 		; AX = Head * Sectors/Track
  6105 000027A7 6699                <1>         cwd
  6106                              <1> 	;pop	dx
  6107 000027A9 5A                  <1> 	pop	edx
  6108                              <1> 	;add	ax, dx
  6109                              <1> 	;pop	dx
  6110                              <1> 	;adc	dx, 0 ; add carry bit
  6111 000027AA 01D0                <1> 	add	eax, edx
  6112                              <1> lbarw2:
  6113 000027AC 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6114 000027AE 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6115 000027B0 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6116                              <1> 				; NOTE: Features register (1F1h, 171h)
  6117                              <1> 				; is not used for ATA device R/W functions. 
  6118                              <1> 				; It is old/obsolete 'write precompensation'
  6119                              <1> 				; register and error register
  6120                              <1> 				; for old ATA/IDE devices.
  6121                              <1> 	; 18/01/2014
  6122                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6123 000027B4 8A0D[E8650000]      <1> 	mov	cl, [hf_m_s]
  6124                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6125                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6126                              <1> 				; bit 6 = 1 = LBA mode
  6127                              <1> 				; bit 7 = 1
  6128 000027BA 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6129                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6130 000027BD 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6131 000027C2 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6132                              <1> 	;or	dh, ch
  6133 000027C5 09C8                <1> 	or	eax, ecx	
  6134                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6135                              <1> 				  ; (Sector Number Register)
  6136                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6137                              <1> 				  ; (Cylinder Low Register)
  6138                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6139                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6140                              <1> 				  ; (Cylinder High Register)
  6141                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6142                              <1> 				  ; (Drive/Head Register)
  6143                              <1> 	
  6144                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6145 000027C7 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6146                              <1> 	;14/02/2015
  6147                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6148 000027CA EB37                <1> 	jmp	short su4
  6149                              <1> su3:
  6150                              <1> 	; 02/02/2015 
  6151                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6152 000027CC 80FC14              <1> 	cmp 	ah, 14h
  6153 000027CF 7603                <1> 	jna 	short chsfnc
  6154                              <1> invldfnc:
  6155                              <1>         ; 14/02/2015  
  6156                              <1> 	;pop	es ; **
  6157                              <1>         ;pop	ax ; ***
  6158                              <1>         ; 24/12/2021
  6159 000027D1 58                  <1> 	pop	eax ; ***
  6160                              <1> 	;jmp	short BAD_COMMAND_POP
  6161 000027D2 EB48                <1>         jmp     short BAD_COMMAND
  6162                              <1> chsfnc:	
  6163                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6164 000027D4 668B4305            <1> 	mov	ax, [ebx+5]
  6165 000027D8 66C1E802            <1> 	SHR	AX,2
  6166 000027DC 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6167                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6168                              <1> 	;;PUSH	DX
  6169                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6170                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6171                              <1> 	;;POP	DX ; * 
  6172                              <1> 	;;POP	ES ; **
  6173                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6174                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6175                              <1> 	;;OR	AH,AL
  6176                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6177                              <1> 	;
  6178 000027DF 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6179 000027E1 243F                <1> 	AND	AL,3FH
  6180 000027E3 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6181 000027E6 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6182 000027E9 88C8                <1> 	MOV	AL,CL
  6183 000027EB C0E806              <1> 	SHR	AL,6
  6184 000027EE 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6185                              <1> 	;;05/01/2015
  6186                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6187 000027F1 A0[E8650000]        <1> 	mov	al, [hf_m_s]
  6188 000027F6 C0E004              <1> 	SHL	AL,4
  6189 000027F9 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6190 000027FC 08F0                <1> 	OR	AL,DH
  6191                              <1> 	;OR	AL,80H or 20H
  6192 000027FE 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6193 00002800 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6194                              <1> su4:
  6195                              <1> 	;POP	ES ; **
  6196                              <1>         ;; 14/02/2015
  6197                              <1>         ;;POP   AX
  6198                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6199                              <1>         ;;PUSH  AX
  6200                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6201                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6202                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6203                              <1> 	;pop     ax ; ***
  6204                              <1> 	; 24/12/2021
  6205 00002803 58                  <1> 	pop	eax ; ***
  6206 00002804 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6207 00002807 29DB                <1>         sub	ebx, ebx
  6208 00002809 88E3                <1> 	mov     bl, ah
  6209                              <1>         ;xor	bh, bh
  6210                              <1>         ;sal	bx, 1
  6211 0000280B 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6212                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6213                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6214                              <1>         ;;JNB   short BAD_COMMAND_POP
  6215                              <1>         ;cmp	bx, M1L
  6216 0000280F 83FB74              <1> 	cmp	ebx, M1L
  6217 00002812 7308                <1> 	jnb	short BAD_COMMAND
  6218                              <1>         ;xchg	bx, si
  6219 00002814 87DE                <1>         xchg	ebx, esi
  6220                              <1> 	;;;POP	AX			; RESTORE AX
  6221                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6222                              <1> 	
  6223                              <1> 	;;PUSH	CX
  6224                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6225                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6226                              <1> 	;SHR	CX,4
  6227                              <1> 	;MOV	AX,ES
  6228                              <1> 	;ADD	AX,CX
  6229                              <1> 	;MOV	ES,AX
  6230                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6231                              <1> 	;;POP	AX
  6232                              <1> 	;;POP	CX
  6233                              <1> 	;;JMP	word [CS:SI+M1]
  6234                              <1> 	;jmp	word [SI+M1]
  6235 00002816 FFA6[6D260000]      <1> 	jmp	dword [esi+M1]
  6236                              <1> ;;BAD_COMMAND_POP:
  6237                              <1> ;;	POP	AX
  6238                              <1> ;;	POP	BX
  6239                              <1> BAD_COMMAND:
  6240 0000281C C605[8F6B0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6241 00002823 B000                <1> 	MOV	AL,0
  6242 00002825 C3                  <1> 	RETn
  6243                              <1> 
  6244                              <1> ;----------------------------------------
  6245                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6246                              <1> ;----------------------------------------
  6247                              <1> 
  6248                              <1> ; 18-1-2015 : one controller reset (not other one)
  6249                              <1> 
  6250                              <1> DISK_RESET:
  6251 00002826 FA                  <1> 	CLI
  6252 00002827 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6253                              <1> 	;JMP	$+2
  6254                              <1> 	IODELAY
  2141 00002829 EB00                <2>  jmp short $+2
  2142 0000282B EB00                <2>  jmp short $+2
  6255                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6256 0000282D 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6257 0000282F E6A1                <1> 	OUT	INTB01,AL
  6258 00002831 FB                  <1> 	STI				; START INTERRUPTS
  6259                              <1> 	; 14/02/2015
  6260                              <1> 	;mov	di, dx
  6261                              <1> 	; 24/12/2021
  6262 00002832 89D7                <1> 	mov	edi, edx	
  6263                              <1> 	; 04/01/2015
  6264                              <1> 	;xor	di,di
  6265                              <1> drst0:
  6266 00002834 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6267                              <1> 	;MOV	DX,HF_REG_PORT
  6268 00002836 668B15[E6650000]    <1> 	MOV	DX,[HF_REG_PORT]
  6269 0000283D EE                  <1> 	OUT	DX,AL			; RESET
  6270                              <1> ;	MOV	CX,10			; DELAY COUNT
  6271                              <1> ;DRD:	DEC	CX
  6272                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6273                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6274 0000283E B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6275 00002843 E876ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6276                              <1>                                         ; 40 micro seconds)
  6277 00002848 A0[916B0000]        <1> 	mov	al,[CONTROL_BYTE]
  6278 0000284D 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6279 0000284F EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6280 00002850 E807040000          <1> 	CALL	NOT_BUSY
  6281 00002855 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6282 00002857 668B15[E4650000]    <1> 	MOV	DX,[HF_PORT]
  6283 0000285E FEC2                <1> 	inc	dl  ; HF_PORT+1
  6284                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6285                              <1>         ;mov	cl, 10
  6286 00002860 B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6287                              <1> drst1:
  6288 00002865 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6289 00002866 3C01                <1> 	CMP	AL,1
  6290                              <1> 	; 04/01/2015
  6291 00002868 740A                <1> 	jz	short drst2
  6292                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6293                              <1>         	; Drive/Head Register - bit 4
  6294 0000286A E2F9                <1> 	loop	drst1
  6295                              <1> DRERR:	
  6296 0000286C C605[8F6B0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6297 00002873 C3                  <1> 	RETn
  6298                              <1> drst2:
  6299                              <1> 	; 14/02/2015
  6300                              <1> 	;mov	dx, di
  6301                              <1> 	; 24/12/2021
  6302 00002874 89FA                <1> 	mov	edx, edi
  6303                              <1> ;drst3:
  6304                              <1> ;	; 05/01/2015
  6305                              <1> ;	shl 	di,1
  6306                              <1> ;	; 04/01/2015
  6307                              <1> ;	mov	ax,[di+hd_cports]
  6308                              <1> ;	cmp	ax,[HF_REG_PORT]
  6309                              <1> ;	je	short drst4
  6310                              <1> ;	mov	[HF_REG_PORT], ax
  6311                              <1> ;	; 03/01/2015
  6312                              <1> ;	mov	ax,[di+hd_ports]
  6313                              <1> ;       mov     [HF_PORT], ax
  6314                              <1> ;	; 05/01/2014
  6315                              <1> ;	shr	di,1
  6316                              <1> ;	; 04/01/2015
  6317                              <1> ;	jmp	short drst0	; reset other controller
  6318                              <1> ;drst4:
  6319                              <1> ;	; 05/01/2015
  6320                              <1> ;	shr	di,1
  6321                              <1> ;	mov	al,[di+hd_dregs]
  6322                              <1> ;	and	al,10h ; bit 4 only
  6323                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6324                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6325                              <1> 	;
  6326 00002876 A0[E8650000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6327 0000287B A801                <1> 	test	al,1
  6328                              <1> ;	jnz	short drst6
  6329 0000287D 7516                <1>         jnz     short drst4
  6330 0000287F 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6331                              <1> ;drst5:
  6332                              <1> drst3:
  6333 00002883 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6334                              <1> 	;mov	dx,di
  6335 00002888 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6336                              <1> 	; 04/01/2014
  6337                              <1> ;	inc	di
  6338                              <1> ;	mov	dx,di
  6339                              <1> ;	cmp	dl,[HF_NUM]
  6340                              <1> ;	jb	short drst3
  6341                              <1> ;DRE:
  6342 0000288D C605[8F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6343 00002894 C3                  <1> 	RETn
  6344                              <1> ;drst6:
  6345                              <1> drst4:		; Drive/Head Register - bit 4
  6346 00002895 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6347                              <1>         ;jmp    short drst5
  6348 00002899 EBE8                <1>         jmp     short drst3
  6349                              <1> 
  6350                              <1> ;----------------------------------------
  6351                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6352                              <1> ;----------------------------------------
  6353                              <1> 
  6354                              <1> RETURN_STATUS:
  6355 0000289B A0[8F6B0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6356 000028A0 C605[8F6B0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6357 000028A7 C3                  <1> 	RETn
  6358                              <1> 
  6359                              <1> ;----------------------------------------
  6360                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6361                              <1> ;----------------------------------------
  6362                              <1> 
  6363                              <1> DISK_READ:
  6364 000028A8 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6365 000028AC E92A020000          <1>         JMP     COMMANDI
  6366                              <1> 
  6367                              <1> ;----------------------------------------
  6368                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6369                              <1> ;----------------------------------------
  6370                              <1> 
  6371                              <1> DISK_WRITE:
  6372 000028B1 C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6373 000028B5 E976020000          <1>         JMP     COMMANDO
  6374                              <1> 
  6375                              <1> ;----------------------------------------
  6376                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6377                              <1> ;----------------------------------------
  6378                              <1> 
  6379                              <1> DISK_VERF:
  6380 000028BA C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6381 000028BE E8E4020000          <1> 	CALL	COMMAND
  6382 000028C3 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6383 000028C5 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6384 000028CA 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6385 000028CC E8E3030000          <1> 	CALL	CHECK_STATUS
  6386                              <1> VERF_EXIT:
  6387 000028D1 C3                  <1> 	RETn
  6388                              <1> 
  6389                              <1> ;----------------------------------------
  6390                              <1> ;	FORMATTING	     (AH = 05H) :
  6391                              <1> ;----------------------------------------
  6392                              <1> 
  6393                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6394 000028D2 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6395                              <1> 	;PUSH	ES
  6396                              <1> 	;PUSH	BX
  6397 000028D6 53                  <1> 	push	ebx
  6398 000028D7 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6399                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6400 000028DC 8A430E              <1> 	mov	al, [ebx+14]
  6401 000028DF 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6402 000028E2 5B                  <1> 	pop	ebx
  6403                              <1> 	;POP	BX
  6404                              <1> 	;POP	ES
  6405 000028E3 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6406                              <1> 
  6407                              <1> ;----------------------------------------
  6408                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6409                              <1> ;----------------------------------------
  6410                              <1> 
  6411                              <1> READ_DASD_TYPE:
  6412                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6413 000028E8 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6414                              <1> 	;PUSH	ES
  6415 000028E9 53                  <1> 	PUSH	eBX
  6416                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6417                              <1> 	;push	cs
  6418                              <1> 	;pop	ds
  6419 000028EA 66BB1000            <1>         mov	bx, KDATA
  6420 000028EE 8EDB                <1> 	mov	ds, bx
  6421                              <1> 	;mov	es, bx
  6422 000028F0 C605[8F6B0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6423 000028F7 8A1D[906B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6424 000028FD 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6425 00002900 38D3                <1> 	CMP	BL,DL
  6426 00002902 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6427 00002904 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6428                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6429 00002909 8A4302              <1> 	mov	al, [ebx+2]
  6430                              <1> 	;MOV	CL,[ES:BX+14]
  6431 0000290C 8A4B0E              <1> 	mov	cl, [ebx+14]
  6432 0000290F F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6433                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6434 00002911 668B0B              <1> 	mov	cx, [ebx]
  6435                              <1> 	;
  6436                              <1> 	; 02/01/2015 
  6437                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6438                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6439 00002914 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6440                              <1> 	;
  6441 00002916 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6442 00002919 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6443 0000291C 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6444                              <1> 	;SUB	AX,AX
  6445 0000291F 28C0                <1> 	sub	al, al
  6446 00002921 B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6447 00002923 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6448                              <1> 	;POP	ES
  6449 00002924 1F                  <1> 	POP	DS
  6450 00002925 F8                  <1> 	CLC				; CLEAR CARRY
  6451                              <1> 	;RETf	2
  6452 00002926 CA0400              <1> 	retf	4
  6453                              <1> RDT_NOT_PRESENT:
  6454                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6455                              <1> 	; 24/12/2021
  6456 00002929 29C0                <1> 	sub	eax, eax
  6457                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6458                              <1> 	;MOV	DX,AX
  6459 0000292B 89C1                <1> 	mov	ecx, eax
  6460 0000292D 89C2                <1> 	mov	edx, eax
  6461 0000292F EBF2                <1> 	JMP	short RDT2
  6462                              <1> 
  6463                              <1> ;----------------------------------------
  6464                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6465                              <1> ;----------------------------------------
  6466                              <1> 
  6467                              <1> GET_PARM_N:
  6468                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6469 00002931 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6470                              <1> 	;PUSH	ES
  6471 00002932 53                  <1> 	PUSH	eBX
  6472                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6473                              <1> 	;MOV	DS,AX
  6474                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6475                              <1> 	;JZ	short G0
  6476                              <1> 	;LES	BX,@HF1_TBL_VEC
  6477                              <1> 	;JMP	SHORT G1
  6478                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6479                              <1> ;G1:
  6480                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6481                              <1> 	; 22/12/2014
  6482                              <1> 	;push	cs
  6483                              <1> 	;pop	ds
  6484 00002933 66BB1000            <1> 	mov	bx, KDATA
  6485 00002937 8EDB                <1> 	mov	ds, bx
  6486                              <1> 	;mov	es, bx
  6487                              <1> 	;
  6488 00002939 80EA80              <1> 	SUB	DL,80H
  6489 0000293C 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6490 0000293F 7340                <1> 	JAE	short G4
  6491                              <1> 	;
  6492 00002941 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6493                              <1> 	; 22/12/2014
  6494 00002943 88D3                <1> 	mov	bl, dl
  6495                              <1> 	;xor	bh, bh  
  6496 00002945 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6497                              <1> 	;add	bx, HF_TBL_VEC
  6498 00002948 81C3[946B0000]      <1> 	add	ebx, HF_TBL_VEC
  6499                              <1> 	;mov	ax, [bx+2]
  6500                              <1> 	;mov	es, ax			; dpt segment
  6501                              <1> 	;mov	bx, [bx]		; dpt offset
  6502 0000294E 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6503                              <1> 
  6504 00002950 C605[8F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6505                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6506 00002957 668B03              <1> 	mov	ax, [ebx]
  6507                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6508 0000295A 6648                <1> 	dec	ax			; max. cylinder number
  6509 0000295C 88C5                <1> 	MOV	CH,AL
  6510 0000295E 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6511 00002962 66D1E8              <1> 	SHR	AX,1
  6512 00002965 66D1E8              <1> 	SHR	AX,1
  6513                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6514 00002968 0A430E              <1> 	or	al, [ebx+14]
  6515 0000296B 88C1                <1> 	MOV	CL,AL
  6516                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6517 0000296D 8A7302              <1> 	mov	dh, [ebx+2]
  6518 00002970 FECE                <1> 	DEC	DH			; 0-N RANGE
  6519 00002972 8A15[906B0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6520                              <1> 	;SUB	AX,AX
  6521                              <1> 	; 24/12/2021
  6522 00002978 29C0                <1> 	sub	eax, eax
  6523                              <1> 	; 27/12/2014 
  6524                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6525                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6526                              <1> 	;mov	di, bx			; HDPT offset
  6527 0000297A 89DF                <1> 	mov	edi, ebx
  6528                              <1> G5:
  6529 0000297C 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6530                              <1> 	;POP	ES
  6531 0000297D 1F                  <1> 	POP	DS
  6532                              <1> 	;RETf	2
  6533 0000297E CA0400              <1> 	retf	4
  6534                              <1> G4:
  6535 00002981 C605[8F6B0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6536                              <1> 	; 24/12/2021
  6537 00002988 29C0                <1> 	sub	eax, eax
  6538 0000298A B407                <1> 	MOV	AH,INIT_FAIL
  6539                              <1> 	;SUB	AL,AL
  6540                              <1> 	;SUB	DX,DX
  6541 0000298C 29D2                <1> 	sub	edx, edx
  6542                              <1> 	;SUB	CX,CX
  6543 0000298E 29C9                <1> 	sub	ecx, ecx
  6544 00002990 F9                  <1> 	STC				; SET ERROR FLAG
  6545 00002991 EBE9                <1> 	JMP	short G5
  6546                              <1> 
  6547                              <1> ;----------------------------------------
  6548                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6549                              <1> ;----------------------------------------
  6550                              <1> 	; 03/01/2015
  6551                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6552                              <1> 	; logical sector per logical track
  6553                              <1> 	; and logical heads - 1 would be set but
  6554                              <1> 	; it is seen as it will be good
  6555                              <1> 	; if physical parameters will be set here
  6556                              <1> 	; because, number of heads <= 16.
  6557                              <1> 	; (logical heads usually more than 16)
  6558                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6559                              <1> 	;	== INT 13h physical parameters
  6560                              <1> 
  6561                              <1> ;INIT_DRV:
  6562                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6563                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6564                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6565                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6566                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6567                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6568                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6569                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6570                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6571                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6572                              <1> ;	SUB	AX,AX
  6573                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6574                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6575                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6576                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6577                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6578                              <1> ;	CALL	CHECK_STATUS
  6579                              <1> ;INIT_EXIT:
  6580                              <1> ;	RETn
  6581                              <1> 
  6582                              <1> ; 04/01/2015
  6583                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6584                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6585                              <1> INIT_DRV:
  6586                              <1> 	;xor	ah,ah
  6587 00002993 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6588 00002995 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6589 00002997 3825[A46B0000]      <1>         cmp     [LBAMode], ah   ; 0
  6590 0000299D 7702                <1> 	ja	short idrv0
  6591 0000299F B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6592                              <1> idrv0:
  6593                              <1> 	; DL = drive number (0 based)
  6594 000029A1 E8BB030000          <1> 	call	GET_VEC
  6595                              <1> 	;push	bx
  6596 000029A6 53                  <1> 	push	ebx ; 21/02/2015
  6597                              <1> 	;add	bx,ax
  6598 000029A7 01C3                <1> 	add	ebx,eax
  6599                              <1> 	;; 05/01/2015
  6600 000029A9 8A25[E8650000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6601                              <1> 	;;and 	ah,1 
  6602 000029AF C0E404              <1> 	shl	ah,4
  6603 000029B2 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6604                              <1> 	;mov	al,[es:bx]
  6605 000029B5 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6606 000029B7 FEC8                <1> 	dec	al	 ; last head number 
  6607                              <1> 	;and	al,0Fh
  6608 000029B9 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6609                              <1> 	;
  6610 000029BB C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6611 000029BF 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6612                              <1> 	;pop	bx
  6613 000029C2 5B                  <1> 	pop	ebx
  6614 000029C3 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6615 000029C5 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6616 000029C7 803D[A46B0000]00    <1> 	cmp	byte [LBAMode],0
  6617 000029CE 7702                <1> 	ja	short idrv1
  6618 000029D0 B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6619                              <1> idrv1:
  6620                              <1> 	;xor	ah,ah
  6621                              <1> 	;add	bx,ax
  6622 000029D2 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6623                              <1> 	;mov	al,[es:bx]
  6624                              <1> 			; sector number
  6625 000029D4 8A03                <1> 	mov	al,[ebx]
  6626 000029D6 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6627 000029D9 28C0                <1> 	sub	al,al
  6628 000029DB 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6629 000029DE E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6630 000029E3 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6631 000029E5 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6632 000029EA 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6633 000029EC E8C3020000          <1> 	call	CHECK_STATUS
  6634                              <1> INIT_EXIT:
  6635 000029F1 C3                  <1> 	RETn
  6636                              <1> 
  6637                              <1> ;----------------------------------------
  6638                              <1> ;	READ LONG	     (AH = 0AH) :
  6639                              <1> ;----------------------------------------
  6640                              <1> 
  6641                              <1> RD_LONG:
  6642                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6643 000029F2 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6644 000029F6 E9E0000000          <1>         JMP     COMMANDI
  6645                              <1> 
  6646                              <1> ;----------------------------------------
  6647                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6648                              <1> ;----------------------------------------
  6649                              <1> 
  6650                              <1> WR_LONG:
  6651                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6652 000029FB C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6653 000029FF E92C010000          <1>         JMP     COMMANDO
  6654                              <1> 
  6655                              <1> ;----------------------------------------
  6656                              <1> ;	SEEK		     (AH = 0CH) :
  6657                              <1> ;----------------------------------------
  6658                              <1> 
  6659                              <1> DISK_SEEK:
  6660 00002A04 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6661 00002A08 E89A010000          <1> 	CALL	COMMAND
  6662 00002A0D 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6663 00002A0F E80C020000          <1> 	CALL	_WAIT
  6664 00002A14 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6665 00002A16 E899020000          <1> 	CALL	CHECK_STATUS
  6666 00002A1B 803D[8F6B0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6667 00002A22 7507                <1> 	JNE	short DS_EXIT
  6668 00002A24 C605[8F6B0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6669                              <1> DS_EXIT:
  6670 00002A2B C3                  <1> 	RETn
  6671                              <1> 
  6672                              <1> ;----------------------------------------
  6673                              <1> ;	TEST DISK READY      (AH = 10H) :
  6674                              <1> ;----------------------------------------
  6675                              <1> 
  6676                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6677 00002A2C E82B020000          <1> 	CALL	NOT_BUSY
  6678 00002A31 751C                <1> 	JNZ	short TR_EX
  6679 00002A33 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6680 00002A36 668B15[E4650000]    <1> 	MOV	DX,[HF_PORT]
  6681 00002A3D 80C206              <1> 	add	dl,6
  6682 00002A40 EE                  <1> 	OUT	DX,AL
  6683 00002A41 E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6684 00002A46 7507                <1> 	JNZ	short TR_EX
  6685 00002A48 C605[8F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6686                              <1> TR_EX:	
  6687 00002A4F C3                  <1> 	RETn
  6688                              <1> 
  6689                              <1> ;----------------------------------------
  6690                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6691                              <1> ;----------------------------------------
  6692                              <1> 
  6693                              <1> HDISK_RECAL:
  6694 00002A50 C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6695 00002A54 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6696 00002A59 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6697 00002A5B E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6698 00002A60 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6699 00002A62 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6700 00002A67 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6701                              <1> RECAL_X:
  6702 00002A69 E846020000          <1> 	CALL	CHECK_STATUS
  6703 00002A6E 803D[8F6B0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6704 00002A75 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6705 00002A77 C605[8F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6706                              <1> RECAL_EXIT:
  6707 00002A7E 803D[8F6B0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6708 00002A85 C3                  <1> 	RETn
  6709                              <1> 
  6710                              <1> ;----------------------------------------
  6711                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6712                              <1> ;----------------------------------------
  6713                              <1> 
  6714                              <1> CTLR_DIAGNOSTIC:
  6715 00002A86 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6716 00002A87 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6717                              <1> 	;AND	AL,0BFH
  6718 00002A89 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6719                              <1> 	;JMP	$+2
  6720                              <1> 	IODELAY
  2141 00002A8B EB00                <2>  jmp short $+2
  2142 00002A8D EB00                <2>  jmp short $+2
  6721 00002A8F E6A1                <1> 	OUT	INTB01,AL
  6722                              <1> 	IODELAY
  2141 00002A91 EB00                <2>  jmp short $+2
  2142 00002A93 EB00                <2>  jmp short $+2
  6723 00002A95 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6724 00002A97 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6725                              <1> 	;JMP	$+2
  6726                              <1> 	IODELAY
  2141 00002A99 EB00                <2>  jmp short $+2
  2142 00002A9B EB00                <2>  jmp short $+2
  6727 00002A9D E621                <1> 	OUT	INTA01,AL
  6728 00002A9F FB                  <1> 	STI
  6729 00002AA0 E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6730 00002AA5 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6731                              <1> 	;MOV	DX, HF_PORT+7
  6732 00002AA7 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  6733 00002AAE 80C207              <1> 	add	dl, 7
  6734 00002AB1 B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6735 00002AB3 EE                  <1> 	OUT	DX,AL
  6736 00002AB4 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6737 00002AB9 B480                <1> 	MOV	AH,TIME_OUT
  6738 00002ABB 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6739                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6740 00002ABD 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  6741 00002AC4 FEC2                <1> 	inc	dl
  6742 00002AC6 EC                  <1> 	IN	AL,DX
  6743 00002AC7 A2[866B0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6744 00002ACC B400                <1> 	MOV	AH,0
  6745 00002ACE 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6746 00002AD0 7402                <1> 	JE	SHORT CD_EXIT
  6747 00002AD2 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6748                              <1> CD_EXIT:
  6749 00002AD4 8825[8F6B0000]      <1> 	MOV	[DISK_STATUS1],AH
  6750 00002ADA C3                  <1> 	RETn
  6751                              <1> 
  6752                              <1> ;----------------------------------------
  6753                              <1> ; COMMANDI				:
  6754                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6755                              <1> ;	NSECTOR RETURNS ZERO		:
  6756                              <1> ;----------------------------------------
  6757                              <1> COMMANDI:
  6758 00002ADB E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6759 00002AE0 724D                <1> 	JC	short CMD_ABORT
  6760                              <1> 	;MOV	DI,BX
  6761 00002AE2 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6762 00002AE4 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6763 00002AE9 7544                <1> 	JNZ	short CMD_ABORT
  6764                              <1> CMD_I1:
  6765 00002AEB E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6766 00002AF0 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6767                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6768 00002AF2 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6769                              <1> 	;MOV	DX,HF_PORT
  6770 00002AF7 668B15[E4650000]    <1> 	mov	dx,[HF_PORT]
  6771 00002AFE FA                  <1> 	CLI
  6772 00002AFF FC                  <1> 	CLD
  6773 00002B00 F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6774 00002B03 FB                  <1> 	STI
  6775 00002B04 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6776 00002B08 7419                <1> 	JZ	CMD_I3
  6777 00002B0A E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6778 00002B0F 721E                <1> 	JC	short TM_OUT
  6779                              <1> 	;MOV	DX,HF_PORT
  6780 00002B11 668B15[E4650000]    <1> 	mov	dx,[HF_PORT]
  6781                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6782 00002B18 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6783 00002B1D EC                  <1> CMD_I2: IN	AL,DX
  6784                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6785 00002B1E 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6786 00002B20 47                  <1> 	INC	eDI
  6787 00002B21 E2FA                <1> 	LOOP	CMD_I2
  6788 00002B23 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6789 00002B28 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6790 00002B2A FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6791 00002B2D 75BC                <1> 	JNZ	SHORT CMD_I1
  6792                              <1> CMD_ABORT:
  6793 00002B2F C3                  <1> TM_OUT: RETn
  6794                              <1> 
  6795                              <1> ;----------------------------------------
  6796                              <1> ; COMMANDO				:
  6797                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6798                              <1> ;	NSECTOR RETURNS ZERO		:
  6799                              <1> ;----------------------------------------
  6800                              <1> COMMANDO:
  6801 00002B30 E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6802 00002B35 72F8                <1> 	JC	short CMD_ABORT
  6803 00002B37 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6804 00002B39 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6805 00002B3E 75EF                <1> 	JNZ	short CMD_ABORT
  6806 00002B40 E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6807 00002B45 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6808                              <1> CMD_O1: ;PUSH	DS
  6809                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6810                              <1> 	;POP	DS
  6811                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6812                              <1> 	;MOV	DX,HF_PORT
  6813                              <1> 	; 01/02/2015
  6814 00002B47 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  6815                              <1> 	;push	es
  6816                              <1> 	;pop	ds
  6817                              <1> 	;mov	cx, 256
  6818 00002B4E B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6819 00002B53 FA                  <1> 	CLI
  6820 00002B54 FC                  <1> 	CLD
  6821 00002B55 F3666F              <1> 	REP	OUTSW
  6822 00002B58 FB                  <1> 	STI
  6823                              <1> 	;POP	DS			; RESTORE DS
  6824 00002B59 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6825 00002B5D 7419                <1> 	JZ	short CMD_O3
  6826 00002B5F E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6827 00002B64 72C9                <1> 	JC	short TM_OUT
  6828                              <1> 	;MOV	DX,HF_PORT
  6829 00002B66 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  6830                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6831 00002B6D B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6832                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6833 00002B72 8A06                <1> 	mov	al, [esi]
  6834 00002B74 EE                  <1> 	OUT	DX,AL
  6835 00002B75 46                  <1> 	INC	eSI
  6836 00002B76 E2FA                <1> 	LOOP	CMD_O2
  6837                              <1> CMD_O3:
  6838 00002B78 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6839 00002B7D 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6840 00002B7F E830010000          <1> 	CALL	CHECK_STATUS
  6841 00002B84 75A9                <1> 	JNZ	short CMD_ABORT
  6842 00002B86 F605[856B0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6843 00002B8D 75B8                <1> 	JNZ	SHORT CMD_O1
  6844                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6845 00002B8F 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  6846                              <1> 	;add	dl, 2
  6847 00002B96 FEC2                <1> 	inc	dl
  6848 00002B98 FEC2                <1> 	inc	dl
  6849 00002B9A EC                  <1> 	IN	AL,DX			;
  6850 00002B9B A8FF                <1> 	TEST	AL,0FFH 		;
  6851 00002B9D 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6852 00002B9F C605[8F6B0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6853                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6854                              <1> CMD_O4:
  6855 00002BA6 C3                  <1> 	RETn
  6856                              <1> 
  6857                              <1> ;--------------------------------------------------------
  6858                              <1> ; COMMAND						:
  6859                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6860                              <1> ; OUTPUT						:
  6861                              <1> ;	BL = STATUS					:
  6862                              <1> ;	BH = ERROR REGISTER				:
  6863                              <1> ;--------------------------------------------------------
  6864                              <1> 
  6865                              <1> COMMAND:
  6866 00002BA7 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6867                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6868                              <1> COMMAND1:
  6869                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6870 00002BA8 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6871                              <1> 	;;POP	CX
  6872 00002BAD 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6873 00002BAF 803D[8F6B0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6874                              <1> 	;JZ	short CMD_TIMEOUT
  6875                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6876                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6877 00002BB6 7507                <1> 	jne	short COMMAND4
  6878                              <1> CMD_TIMEOUT:
  6879 00002BB8 C605[8F6B0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6880                              <1> COMMAND4:
  6881 00002BBF 5B                  <1> 	POP	eBX
  6882 00002BC0 803D[8F6B0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6883 00002BC7 C3                  <1> 	RETn
  6884                              <1> COMMAND2:
  6885 00002BC8 5B                  <1> 	POP	eBX
  6886 00002BC9 57                  <1> 	PUSH	eDI
  6887 00002BCA C605[876B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6888 00002BD1 FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6889 00002BD2 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6890                              <1> 	;AND	AL,0BFH
  6891 00002BD4 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6892                              <1> 	;JMP	$+2
  6893                              <1> 	IODELAY
  2141 00002BD6 EB00                <2>  jmp short $+2
  2142 00002BD8 EB00                <2>  jmp short $+2
  6894 00002BDA E6A1                <1> 	OUT	INTB01,AL
  6895 00002BDC E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6896 00002BDE 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6897                              <1> 	;JMP	$+2
  6898                              <1> 	IODELAY
  2141 00002BE0 EB00                <2>  jmp short $+2
  2142 00002BE2 EB00                <2>  jmp short $+2
  6899 00002BE4 E621                <1> 	OUT	INTA01,AL
  6900 00002BE6 FB                  <1> 	STI
  6901 00002BE7 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6902                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6903 00002BE9 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  6904 00002BF0 FEC2                <1> 	inc	dl
  6905 00002BF2 F605[916B0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6906 00002BF9 7411                <1> 	JZ	short COMMAND3
  6907 00002BFB 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6908 00002BFE 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6909 00002C00 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6910 00002C02 7208                <1> 	JB	short COMMAND3
  6911 00002C04 3C40                <1> 	CMP	AL,40H
  6912 00002C06 7704                <1> 	JA	short COMMAND3
  6913 00002C08 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6914                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6915                              <1> COMMAND3:
  6916 00002C0C 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6917 00002C10 EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6918                              <1> 	IODELAY
  2141 00002C11 EB00                <2>  jmp short $+2
  2142 00002C13 EB00                <2>  jmp short $+2
  6919 00002C15 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6920 00002C16 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6921 00002C18 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6922 00002C1C 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6923 00002C1E 5F                  <1> 	POP	eDI
  6924 00002C1F C3                  <1> 	RETn				; ZERO FLAG IS SET
  6925                              <1> 
  6926                              <1> ;CMD_TIMEOUT:
  6927                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6928                              <1> ;COMMAND4:
  6929                              <1> ;	POP	BX
  6930                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6931                              <1> ;	RETn
  6932                              <1> 
  6933                              <1> ;----------------------------------------
  6934                              <1> ;	WAIT FOR INTERRUPT		:
  6935                              <1> ;----------------------------------------
  6936                              <1> ;WAIT:
  6937                              <1> _WAIT:
  6938 00002C20 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6939                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6940                              <1> 	;CLC
  6941                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6942                              <1> 	;INT	15H
  6943                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6944                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6945                              <1> 
  6946                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6947                              <1> 	;; 21/02/2015
  6948                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6949                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6950 00002C21 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6951                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6952                              <1> ;-----	WAIT LOOP
  6953                              <1> 
  6954                              <1> WT1:	
  6955                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6956 00002C26 F605[876B0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6957                              <1> 	;LOOPZ	WT1
  6958 00002C2D 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6959                              <1> 	;DEC	BL
  6960                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6961                              <1> 
  6962                              <1> WT1_hi:
  6963 00002C2F E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6964 00002C31 A810                <1> 	test	al, 10h			; transition on memory
  6965 00002C33 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6966                              <1> WT1_lo:
  6967 00002C35 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6968 00002C37 A810                <1> 	test	al, 10h			
  6969 00002C39 74FA                <1> 	jz	short WT1_lo
  6970 00002C3B E2E9                <1> 	loop	WT1
  6971                              <1> 	;;or	bl, bl
  6972                              <1> 	;;jz	short WT2	
  6973                              <1> 	;;dec	bl
  6974                              <1> 	;;jmp	short WT1
  6975                              <1> 	;dec	bl
  6976                              <1> 	;jnz	short WT1	
  6977                              <1> 
  6978 00002C3D C605[8F6B0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6979 00002C44 EB0E                <1> 	JMP	SHORT WT4
  6980 00002C46 C605[8F6B0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6981 00002C4D C605[876B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6982 00002C54 803D[8F6B0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6983 00002C5B C3                  <1> 	RETn
  6984                              <1> 
  6985                              <1> ;----------------------------------------
  6986                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6987                              <1> ;----------------------------------------
  6988                              <1> NOT_BUSY:
  6989 00002C5C FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6990                              <1> 	;PUSH	eBX
  6991                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6992 00002C5D 668B15[E4650000]    <1> 	mov	DX, [HF_PORT]
  6993 00002C64 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6994                              <1> 	;MOV	BL,DELAY_1
  6995                              <1> 					; wait for 10 seconds
  6996                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6997                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6998                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6999 00002C67 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  7000                              <1> 	;
  7001                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  7002                              <1> NB1:	
  7003 00002C6C EC                  <1> 	IN	AL,DX			; CHECK STATUS
  7004                              <1> 	;TEST	AL,ST_BUSY
  7005 00002C6D 2480                <1> 	and	al, ST_BUSY
  7006                              <1> 	;LOOPNZ	NB1
  7007 00002C6F 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  7008                              <1> 	;DEC	BL			
  7009                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  7010                              <1> 
  7011 00002C71 E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  7012 00002C73 A810                <1> 	TEST	AL,010H			; transition on memory
  7013 00002C75 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  7014 00002C77 E461                <1> NB1_lo: IN	AL,SYS1
  7015 00002C79 A810                <1> 	TEST	AL,010H
  7016 00002C7B 74FA                <1> 	JZ	short NB1_lo
  7017 00002C7D E2ED                <1> 	LOOP	NB1
  7018                              <1> 	;dec	bl
  7019                              <1> 	;jnz	short NB1
  7020                              <1> 	;
  7021                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  7022                              <1> ;;	jb	short NB1
  7023                              <1> 	;
  7024                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  7025                              <1> 	;JMP	SHORT NB3
  7026 00002C7F B080                <1> 	mov	al, TIME_OUT
  7027                              <1> NB2:	
  7028                              <1> 	;MOV	byte [DISK_STATUS1],0
  7029                              <1> ;NB3:	
  7030                              <1> 	;POP	eBX
  7031 00002C81 A2[8F6B0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  7032                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  7033 00002C86 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  7034 00002C88 C3                  <1> 	RETn
  7035                              <1> 
  7036                              <1> ;----------------------------------------
  7037                              <1> ;	WAIT FOR DATA REQUEST		:
  7038                              <1> ;----------------------------------------
  7039                              <1> WAIT_DRQ:
  7040                              <1> 	;MOV	CX,DELAY_3
  7041                              <1> 	;MOV	DX,HF_PORT+7
  7042 00002C89 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  7043 00002C90 80C207              <1> 	add	dl, 7
  7044                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7045                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7046                              <1> 					; (but it is written as 2000
  7047                              <1> 					; micro seconds in ATORGS.ASM file
  7048                              <1> 					; of Award Bios - 1999, D1A0622)
  7049 00002C93 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7050 00002C98 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7051 00002C99 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7052 00002C9B 7516                <1> 	JNZ	short WQ_OK
  7053                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7054                              <1> WQ_hi:	
  7055 00002C9D E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7056 00002C9F A810                <1> 	TEST	AL,010H			; transition on memory
  7057 00002CA1 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7058 00002CA3 E461                <1> WQ_lo:  IN      AL,SYS1
  7059 00002CA5 A810                <1> 	TEST	AL,010H
  7060 00002CA7 74FA                <1> 	JZ	SHORT WQ_lo
  7061 00002CA9 E2ED                <1> 	LOOP	WQ_1
  7062                              <1> 
  7063 00002CAB C605[8F6B0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7064 00002CB2 F9                  <1> 	STC
  7065                              <1> WQ_OK:
  7066 00002CB3 C3                  <1> 	RETn
  7067                              <1> ;WQ_OK:	;CLC
  7068                              <1> ;	RETn
  7069                              <1> 
  7070                              <1> ;----------------------------------------
  7071                              <1> ;	CHECK FIXED DISK STATUS 	:
  7072                              <1> ;----------------------------------------
  7073                              <1> CHECK_STATUS:
  7074 00002CB4 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7075 00002CB9 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7076 00002CBB A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7077 00002CBD 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7078 00002CBF E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7079                              <1> CHECK_S1:
  7080 00002CC4 803D[8F6B0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7081 00002CCB C3                  <1> 	RETn
  7082                              <1> 
  7083                              <1> ;----------------------------------------
  7084                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7085                              <1> ;----------------------------------------
  7086                              <1> CHECK_ST:
  7087                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7088 00002CCC 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]
  7089 00002CD3 80C207              <1> 	add	dl, 7
  7090 00002CD6 EC                  <1> 	IN	AL,DX
  7091 00002CD7 A2[856B0000]        <1> 	MOV	[HF_STATUS],AL
  7092 00002CDC B400                <1> 	MOV	AH,0
  7093 00002CDE A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7094 00002CE0 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7095 00002CE2 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7096 00002CE4 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7097 00002CE6 7514                <1> 	JNZ	short CKST_EXIT
  7098 00002CE8 B4AA                <1> 	MOV	AH,NOT_RDY
  7099 00002CEA A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7100 00002CEC 740E                <1> 	JZ	short CKST_EXIT
  7101 00002CEE B440                <1> 	MOV	AH,BAD_SEEK
  7102 00002CF0 A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7103 00002CF2 7408                <1> 	JZ	short CKST_EXIT
  7104 00002CF4 B411                <1> 	MOV	AH,DATA_CORRECTED
  7105 00002CF6 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7106 00002CF8 7502                <1> 	JNZ	short CKST_EXIT
  7107 00002CFA B400                <1> 	MOV	AH,0
  7108                              <1> CKST_EXIT:
  7109 00002CFC 8825[8F6B0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7110 00002D02 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7111 00002D05 7403                <1> 	JZ	short CKST_EX1
  7112 00002D07 80FC00              <1> 	CMP	AH,0
  7113                              <1> CKST_EX1:
  7114 00002D0A C3                  <1> 	RETn
  7115                              <1> 
  7116                              <1> ;----------------------------------------
  7117                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7118                              <1> ;----------------------------------------
  7119                              <1> CHECK_ER:
  7120                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7121 00002D0B 668B15[E4650000]    <1> 	mov	dx, [HF_PORT]		;
  7122 00002D12 FEC2                <1> 	inc	dl
  7123 00002D14 EC                  <1> 	IN	AL,DX
  7124 00002D15 A2[866B0000]        <1> 	MOV	[HF_ERROR],AL
  7125 00002D1A 53                  <1> 	PUSH	eBX ; 21/02/2015
  7126 00002D1B B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7127 00002D20 D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7128 00002D22 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7129 00002D24 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7130 00002D26 BB[D8650000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7131 00002D2B 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7132                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7133                              <1> 	;mov	ah, [bx]
  7134 00002D2D 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7135 00002D2F 8825[8F6B0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7136 00002D35 5B                  <1> 	POP	eBX
  7137 00002D36 80FC00              <1> 	CMP	AH,0
  7138 00002D39 C3                  <1> 	RETn
  7139                              <1> 
  7140                              <1> ;--------------------------------------------------------
  7141                              <1> ; CHECK_DMA						:
  7142                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7143                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7144                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7145                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7146                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7147                              <1> ;  -ERROR OTHERWISE					:
  7148                              <1> ;--------------------------------------------------------
  7149                              <1> CHECK_DMA:
  7150                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7151                              <1> 	; 24/12/2021
  7152 00002D3A 50                  <1> 	push	eax
  7153 00002D3B 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7154 00002D3F F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7155 00002D43 7404                <1> 	JZ	short CKD1
  7156 00002D45 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7157 00002D49 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7158 00002D4C 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7159 00002D4E 7207                <1> 	JB	short CKDERR		; TOO MANY
  7160 00002D50 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7161 00002D52 7203                <1> 	JB	short CKDERR		; ERROR
  7162 00002D54 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7163                              <1> 	;POP	AX
  7164                              <1> 	; 24/12/2021
  7165 00002D55 58                  <1> 	pop	eax
  7166 00002D56 C3                  <1> 	RETn				; NORMAL RETURN
  7167 00002D57 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7168 00002D58 C605[8F6B0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7169                              <1> 	;POP	AX
  7170                              <1> 	; 24/12/2021
  7171 00002D5F 58                  <1> 	pop	eax	
  7172 00002D60 C3                  <1> 	RETn
  7173                              <1> 
  7174                              <1> ;----------------------------------------
  7175                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7176                              <1> ;----------------------------------------
  7177                              <1> 					
  7178                              <1> ; INPUT -> DL = 0 based drive number
  7179                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7180                              <1> 
  7181                              <1> GET_VEC:
  7182                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7183                              <1> 	;MOV	ES,AX
  7184                              <1> 	;TEST	DL,1
  7185                              <1> 	;JZ	short GV_0
  7186                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7187                              <1> ;	JMP	SHORT GV_EXIT
  7188                              <1> ;GV_0:
  7189                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7190                              <1> ;
  7191                              <1> 	;xor	bh, bh
  7192 00002D61 31DB                <1> 	xor	ebx, ebx
  7193 00002D63 88D3                <1> 	mov	bl, dl
  7194                              <1> 	;;02/01/2015
  7195                              <1> 	;;shl	bl, 1			; port address offset
  7196                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7197                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7198 00002D65 C0E302              <1> 	shl	bl, 2	;;
  7199                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7200 00002D68 81C3[946B0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7201                              <1> 	;push	word [bx+2]		; dpt segment
  7202                              <1> 	;pop	es
  7203                              <1> 	;mov	bx, [bx]		; dpt offset
  7204 00002D6E 8B1B                <1> 	mov	ebx, [ebx]		
  7205                              <1> ;GV_EXIT:
  7206 00002D70 C3                  <1> 	RETn
  7207                              <1> 
  7208                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7209                              <1> hdc1_int: ; 21/02/2015
  7210                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7211                              <1> ;								:
  7212                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7213                              <1> ;								:
  7214                              <1> ;----------------------------------------------------------------
  7215                              <1> 
  7216                              <1> ; 22/12/2014
  7217                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7218                              <1> ;	 '11/15/85'
  7219                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7220                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7221                              <1> 
  7222                              <1> ;int_76h:
  7223                              <1> HD_INT:
  7224                              <1> 	;push	ax
  7225                              <1> 	; 24/12/2021
  7226 00002D71 50                  <1> 	push	eax
  7227 00002D72 1E                  <1> 	push	ds
  7228                              <1> 	;CALL	DDS
  7229                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7230 00002D73 66B81000            <1> 	mov	ax, KDATA
  7231 00002D77 8ED8                <1> 	mov 	ds, ax
  7232                              <1> 	;
  7233                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7234                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7235 00002D79 C605[876B0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7236                              <1> 	;
  7237                              <1> 	;push	dx
  7238                              <1> 	; 24/12/2021
  7239 00002D80 52                  <1> 	push	edx
  7240 00002D81 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7241                              <1> 					; Clear Controller
  7242                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7243 00002D85 EC                  <1> 	in	al, dx			;
  7244                              <1> 	;pop	dx
  7245                              <1> 	; 24/12/2021
  7246 00002D86 5A                  <1> 	pop	edx
  7247                              <1> 	NEWIODELAY
  2146 00002D87 E6EB                <2>  out 0EBh,al
  7248                              <1> 	;
  7249 00002D89 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7250 00002D8B E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7251                              <1> 	;JMP	$+2			; WAIT
  7252                              <1> 	NEWIODELAY
  2146 00002D8D E6EB                <2>  out 0EBh,al
  7253 00002D8F E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7254 00002D91 1F                  <1> 	pop	ds
  7255                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7256                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7257                              <1> 	;INT	15H			;  INTERRUPT
  7258                              <1> irq15_iret: ; 25/02/2015
  7259                              <1> 	;pop	ax
  7260                              <1> 	; 24/12/2021
  7261 00002D92 58                  <1> 	pop	eax
  7262 00002D93 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7263                              <1> 
  7264                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7265                              <1> hdc2_int: ; 21/02/2015
  7266                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7267                              <1> ;								:
  7268                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7269                              <1> ;								:
  7270                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7271                              <1> 
  7272                              <1> ;int_77h:
  7273                              <1> HD1_INT:
  7274                              <1> 	;push	ax
  7275                              <1> 	; 24/12/2021
  7276 00002D94 50                  <1> 	push	eax
  7277                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7278                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7279 00002D95 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7280 00002D97 E6A0                <1> 	out	0A0h, al
  7281 00002D99 EB00                <1>         jmp short $+2
  7282 00002D9B EB00                <1> 	jmp short $+2
  7283 00002D9D E4A0                <1> 	in	al, 0A0h
  7284 00002D9F 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7285 00002DA1 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7286                              <1> 	;
  7287 00002DA3 1E                  <1> 	push	ds
  7288                              <1> 	;CALL	DDS
  7289                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7290 00002DA4 66B81000            <1> 	mov	ax, KDATA
  7291 00002DA8 8ED8                <1> 	mov 	ds, ax
  7292                              <1> 	;
  7293                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7294                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7295 00002DAA 800D[876B0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7296                              <1> 	;
  7297                              <1> 	;push	dx
  7298                              <1> 	; 24/12/2021
  7299 00002DB1 52                  <1> 	push	edx
  7300 00002DB2 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7301                              <1> 					; Clear Controller (Award BIOS 1999)
  7302 00002DB6 EBCD                <1> 	jmp	short Clear_IRQ1415
  7303                              <1> 
  7304                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7305                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7306                              <1> 
  7307                              <1> ;////////////////////////////////////////////////////////////////////
  7308                              <1> ;; END OF DISK I/O SYTEM ///
  2085                                  %include 'memory.inc'  ; 09/03/2015
  2086                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2087                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.1) - MEMORY.INC
  2088                              <1> ; Last Modification: 31/12/2021
  2089                              <1> ;
  2090                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2091                              <1> 
  2092                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2093                              <1> 
  2094                              <1> ;;04/11/2014 (unix386.s)	
  2095                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2096                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2097                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2098                              <1> ;;
  2099                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2100                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2101                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2102                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2103                              <1> 
  2104                              <1> ; 27/04/2015
  2105                              <1> ; 09/03/2015
  2106                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2107                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2108                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2109                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2110                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2111                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2112                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2113                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2114                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2115                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2116                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2117                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2118                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2119                              <1> SWP_DISK_READ_ERR 	   equ 40
  2120                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2121                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2122                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2123                              <1> SWP_DISK_WRITE_ERR         equ 44
  2124                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2125                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2126                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2127                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2128                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2129                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2130                              <1> 					; (Indicates that the page is not allocated
  2131                              <1> 					; for the process, it is a shared or system
  2132                              <1>                                         ; page, it must not be deallocated!)
  2133                              <1> ; 14/12/2020
  2134                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2135                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2136                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2137                              <1> 				; (Out of memory allocation table)	
  2138                              <1> ;
  2139                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2140                              <1> ;;
  2141                              <1> ;; 10/10/2014
  2142                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2143                              <1> ;;
  2144                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2145                              <1> ;;	(virtual address = physical address)
  2146                              <1> ;; KERNEL PAGE TABLES:
  2147                              <1> ;;	Kernel page directory and all page tables are
  2148                              <1> ;;	on memory as initialized, as equal to physical memory
  2149                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2150                              <1> ;;
  2151                              <1> ;;	what for: User pages may be swapped out, when accessing
  2152                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2153                              <1> ;;	kernel would have to swap it in! But it is also may be
  2154                              <1> ;;	in use by a user process. (In system/kernel mode
  2155                              <1> ;;	kernel can access all memory pages even if they are
  2156                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2157                              <1> ;;	cause conflicts.) 
  2158                              <1> ;;	
  2159                              <1> ;;	As result of these conditions,
  2160                              <1> ;;	all kernel pages must be initialized as equal to 
  2161                              <1> ;;	physical layout for preventing page faults. 
  2162                              <1> ;;	Also, calling "allocate page" procedure after
  2163                              <1> ;;	a page fault can cause another page fault (double fault)
  2164                              <1> ;;	if all kernel page tables would not be initialized.
  2165                              <1> ;;
  2166                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2167                              <1> ;;	memory allocation table. (double word aligned)
  2168                              <1> ;;
  2169                              <1> ;;	[next_page] = first/next free space to be searched
  2170                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2171                              <1> ;;
  2172                              <1> ;;	[last_page] = End of memory (users space), as offset
  2173                              <1> ;;	to memory allocation table. (double word aligned)
  2174                              <1> ;;
  2175                              <1> ;; USER PAGE TABLES:
  2176                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2177                              <1> ;;		'ready only' marked copies of the 
  2178                              <1> ;;		parent process's page table entries (for
  2179                              <1> ;;		same physical memory).
  2180                              <1> ;;		(A page will be copied to a new page after
  2181                              <1> ;;		 if it causes R/W page fault.)
  2182                              <1> ;;
  2183                              <1> ;;	Every user process has own (different)
  2184                              <1> ;;	page directory and page tables.	
  2185                              <1> ;;
  2186                              <1> ;;	Code starts at virtual address 0, always.
  2187                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2188                              <1> ;;	(Programs can be written/developed as simple
  2189                              <1> ;;	 flat memory programs.)
  2190                              <1> ;;
  2191                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2192                              <1> ;;	Memory page will be allocated by kernel only 
  2193                              <1> ;;		(in kernel/system mode only).
  2194                              <1> ;;	* After a
  2195                              <1> ;;	  - 'not present' page fault
  2196                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2197                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2198                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2199                              <1> ;;	  request by running process.
  2200                              <1> ;;	* While creating a process, allocating a new buffer,
  2201                              <1> ;;	  new page tables etc.
  2202                              <1> ;;
  2203                              <1> ;;	At first,
  2204                              <1> ;;	- 'allocate page' procedure will be called;
  2205                              <1> ;,	   if it will return with a valid (>0) physical address
  2206                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2207                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2208                              <1> ;;	- 'allocate page' will be called for allocating page
  2209                              <1> ;;	   directory, page table and running space (data/code).
  2210                              <1> ;;	- every successful 'allocate page' call will decrease
  2211                              <1> ;;	  'free_pages' count (pointer).
  2212                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2213                              <1> ;;	  if 'free_pages' points to a ZERO.
  2214                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2215                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2216                              <1> ;;	  error except errors caused by attribute conflicts.
  2217                              <1> ;;	 (swapper functions)	 
  2218                              <1> ;;					
  2219                              <1> ;;	At second,
  2220                              <1> ;;	- page directory entry will be updated then page table
  2221                              <1> ;;	  entry will be updated.		
  2222                              <1> ;;
  2223                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2224                              <1> ;;	- M.A.T. has a size according to available memory as
  2225                              <1> ;;	  follows:
  2226                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2227                              <1> ;;		  - a bit with value of 0 means allocated page
  2228                              <1> ;;		  - a bit with value of 1 means a free page
  2229                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2230                              <1> ;;	  depending on M.A.T.
  2231                              <1> ;;		(NOTE: Free page count will not be checked
  2232                              <1> ;;		again -on M.A.T.- after initialization. 
  2233                              <1> ;;		Kernel will trust on initial count.)
  2234                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2235                              <1> ;;	  and it will be increased by deallocation procedures.
  2236                              <1> ;;	
  2237                              <1> ;;	- Available memory will be calculated during
  2238                              <1> ;;	  the kernel's initialization stage (in real mode).
  2239                              <1> ;;	  Memory allocation table and kernel page tables 
  2240                              <1> ;;	  will be formatted/sized as result of available
  2241                              <1> ;;	  memory calculation before paging is enabled.
  2242                              <1> ;;
  2243                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2244                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2245                              <1> ;;	- Memory allocation for kernel page directory size 
  2246                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2247                              <1> ;;	  for page tables)
  2248                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2249                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2250                              <1> ;;	- User (available) space will be started 
  2251                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2252                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2253                              <1> ;;	  memory allocation table and kernel's page directory
  2254                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2255                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2256                              <1> ;; 	  for buffers.
  2257                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2258                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2259                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2260                              <1> ;;
  2261                              <1> ;; For 1GB Available Memory:
  2262                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2263                              <1> ;;	- Memory allocation for kernel page directory size 
  2264                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2265                              <1> ;;	  for page tables)
  2266                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2267                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2268                              <1> ;;	- User (available) space will be started 
  2269                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2270                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2271                              <1> ;;	  memory allocation table and kernel's page directory
  2272                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2273                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2274                              <1> ;; 	  for buffers.
  2275                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2276                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2277                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2278                              <1> ;;
  2279                              <1> ;;
  2280                              <1> 
  2281                              <1> ;;************************************************************************************
  2282                              <1> ;; 
  2283                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2284                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2285                              <1> 
  2286                              <1> ;; Main factor: "sys fork" system call 
  2287                              <1> ;;	
  2288                              <1> ;; 		FORK
  2289                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2290                              <1> ;;  writable pages ---->|
  2291                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2292                              <1> ;; 
  2293                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2294                              <1> ;; 
  2295                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2296                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2297                              <1> ;;       -while R/W bit is 0-. 
  2298                              <1> ;; 
  2299                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2300                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2301                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2302                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2303                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2304                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2305                              <1> ;; 
  2306                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2307                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2308                              <1> ;;   Parent's PTE attributes are not changed.
  2309                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2310                              <1> ;;    destroy/mix previous fork result).
  2311                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2312                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2313                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2314                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2315                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2316                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2317                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2318                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2319                              <1> ;; 
  2320                              <1> ;; !? WHAT FOR (duplication after duplication):
  2321                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2322                              <1> ;; program/executable code continues from specified location as child process, 
  2323                              <1> ;; returns back previous code location as parent process, every child after 
  2324                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2325                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2326                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2327                              <1> ;; was copied to child's process segment (all of code and data) according to
  2328                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2329                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2330                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2331                              <1> ;; (complete running image of parent process) to the child process; 
  2332                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2333                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2334                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2335                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2336                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2337                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2338                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2339                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2340                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2341                              <1> ;; for sharing same read only pages between parent and child processes.
  2342                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2343                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2344                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2345                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2346                              <1> ;; -deallocation problem-.
  2347                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2348                              <1> ;; 
  2349                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2350                              <1> ;; # Page fault handler will do those:
  2351                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2352                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2353                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2354                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2355                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2356                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2357                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2358                              <1> ;;     to child process.)	
  2359                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2360                              <1> ;; # Page fault handler will do those:
  2361                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2362                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2363                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2364                              <1> ;;     address or not. 
  2365                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2366                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2367                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2368                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2369                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2370                              <1> ;; 
  2371                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2372                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2373                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2374                              <1> ;;       duplication method details, it is not possible multiple child processes
  2375                              <1> ;;       were using same page with duplicated PTEs.
  2376                              <1> ;; 
  2377                              <1> ;;************************************************************************************   
  2378                              <1> 
  2379                              <1> ;; 08/10/2014
  2380                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2381                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2382                              <1> 
  2383                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2384                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2385                              <1> ;; (25/08/2014, Revision: 5057) file 
  2386                              <1> ;; by KolibriOS Team (2004-2012)
  2387                              <1> 
  2388                              <1> allocate_page:
  2389                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2390                              <1> 	; 01/07/2015
  2391                              <1> 	; 05/05/2015
  2392                              <1> 	; 30/04/2015
  2393                              <1> 	; 16/10/2014
  2394                              <1> 	; 08/10/2014
  2395                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2396                              <1> 	;
  2397                              <1> 	; INPUT -> none
  2398                              <1> 	;
  2399                              <1> 	; OUTPUT ->
  2400                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2401                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2402                              <1> 	;
  2403                              <1> 	;	CF = 1 and EAX = 0 
  2404                              <1> 	; 		   if there is not a free page to be allocated	
  2405                              <1> 	;
  2406                              <1> 	; Modified Registers -> none (except EAX)
  2407                              <1> 	;
  2408 00002DB8 A1[006B0000]        <1> 	mov	eax, [free_pages]
  2409 00002DBD 21C0                <1> 	and	eax, eax
  2410 00002DBF 7438                <1> 	jz	short out_of_memory
  2411                              <1> 	;
  2412 00002DC1 53                  <1> 	push	ebx
  2413 00002DC2 51                  <1> 	push	ecx
  2414                              <1> 	;
  2415 00002DC3 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2416 00002DC8 89D9                <1> 	mov	ecx, ebx
  2417                              <1>  				     ; NOTE: 32 (first_page) is initial
  2418                              <1> 				     ; value of [next_page].
  2419                              <1> 				     ; It points to the first available
  2420                              <1> 				     ; page block for users (ring 3) ...	
  2421                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2422                              <1> 				     ; (at the of the first 4 MB)		
  2423 00002DCA 031D[046B0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2424                              <1> 				 ; next_free_page >> 5
  2425 00002DD0 030D[086B0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2426                              <1> 				 ; (total_pages - 1) >> 5
  2427                              <1> al_p_scan:
  2428 00002DD6 39CB                <1> 	cmp	ebx, ecx
  2429 00002DD8 770A                <1> 	ja	short al_p_notfound
  2430                              <1> 	;
  2431                              <1> 	; 01/07/2015
  2432                              <1> 	; AMD64 Architecture Programmers Manual
  2433                              <1> 	; Volume 3:
  2434                              <1> 	; General-Purpose and System Instructions
  2435                              <1> 	;
  2436                              <1> 	; BSF - Bit Scan Forward
  2437                              <1> 	;
  2438                              <1> 	;   Searches the value in a register or a memory location
  2439                              <1> 	;   (second operand) for the least-significant set bit. 
  2440                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2441                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2442                              <1> 	;   register (first operand). If the second operand contains 0, 
  2443                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2444                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2445                              <1> 	;   of the searched value
  2446                              <1> 	;
  2447 00002DDA 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2448                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2449                              <1> 			   ; loads the destination with an index to
  2450                              <1> 			   ; first set bit. (0 -> 31) 
  2451                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2452 00002DDD 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2453                              <1> 			 ;
  2454                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2455                              <1> 			 ;	  with value of 1 means 
  2456                              <1> 			 ;	  the corresponding page is free 
  2457                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2458 00002DDF 83C304              <1> 	add	ebx, 4
  2459                              <1> 			 ; We return back for searching next page block
  2460                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2461                              <1> 			 ;	 we always will find at least 1 free page here.
  2462 00002DE2 EBF2                <1>         jmp     short al_p_scan
  2463                              <1> 	;
  2464                              <1> al_p_notfound:
  2465 00002DE4 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2466 00002DEA 890D[046B0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2467                              <1> 				 ; (deallocate_page procedure will change it)
  2468 00002DF0 31C0                <1> 	xor	eax, eax
  2469 00002DF2 A3[006B0000]        <1> 	mov	[free_pages], eax ; 0
  2470 00002DF7 59                  <1> 	pop	ecx
  2471 00002DF8 5B                  <1> 	pop	ebx
  2472                              <1> 	;
  2473                              <1> ; 24/12/2021
  2474                              <1> ; ('swap_out' procedure call is disabled)
  2475                              <1> 
  2476                              <1> out_of_memory:
  2477                              <1> ;	call	swap_out
  2478                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2479                              <1> ;	;
  2480                              <1> ;	sub 	eax, eax ; 0
  2481 00002DF9 F9                  <1> 	stc
  2482 00002DFA C3                  <1> 	retn
  2483                              <1> 
  2484                              <1> al_p_found:
  2485 00002DFB 89D9                <1> 	mov	ecx, ebx
  2486 00002DFD 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2487 00002E03 890D[046B0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2488                              <1> 				 ; address/offset (to the next)
  2489 00002E09 FF0D[006B0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2490                              <1> 	;
  2491 00002E0F 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2492                              <1> 				 ; is copied into the Carry Flag and then cleared
  2493                              <1> 				 ; in the destination.
  2494                              <1> 				 ;
  2495                              <1> 				 ; Reset the bit which is corresponding to the 
  2496                              <1> 				 ; (just) allocated page.
  2497                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2498 00002E12 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2499 00002E15 01C8                <1> 	add	eax, ecx	 ; = page number
  2500 00002E17 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2501                              <1> 	; EAX = physical address of memory page
  2502                              <1> 	;
  2503                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2504                              <1> 	;       according to this EAX value...
  2505 00002E1A 59                  <1> 	pop	ecx
  2506 00002E1B 5B                  <1> 	pop	ebx
  2507                              <1> al_p_ok:
  2508 00002E1C C3                  <1> 	retn
  2509                              <1> 
  2510                              <1> make_page_dir:
  2511                              <1> 	; 18/04/2015
  2512                              <1> 	; 12/04/2015
  2513                              <1> 	; 23/10/2014
  2514                              <1> 	; 16/10/2014
  2515                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2516                              <1> 	;
  2517                              <1> 	; INPUT ->
  2518                              <1> 	;	none
  2519                              <1> 	; OUTPUT ->
  2520                              <1> 	;	(EAX = 0)
  2521                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2522                              <1> 	;	cf = 0 ->
  2523                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2524                              <1> 	;		  process/user.
  2525                              <1> 	;
  2526                              <1> 	; Modified Registers -> EAX
  2527                              <1> 	;
  2528 00002E1D E896FFFFFF          <1> 	call	allocate_page
  2529 00002E22 7216                <1> 	jc	short mkpd_error
  2530                              <1> 	;
  2531 00002E24 A3[116F0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2532                              <1> 				  ; (Physical address)
  2533                              <1> clear_page:
  2534                              <1> 	; 18/04/2015
  2535                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2536                              <1> 	;
  2537                              <1> 	; INPUT ->
  2538                              <1> 	;	EAX = physical address of the page
  2539                              <1> 	; OUTPUT ->
  2540                              <1> 	;	all bytes of the page will be cleared
  2541                              <1> 	;
  2542                              <1> 	; Modified Registers -> none
  2543                              <1> 	;
  2544 00002E29 57                  <1> 	push	edi
  2545 00002E2A 51                  <1> 	push	ecx
  2546 00002E2B 50                  <1> 	push	eax
  2547 00002E2C B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2548 00002E31 89C7                <1> 	mov	edi, eax
  2549 00002E33 31C0                <1> 	xor	eax, eax
  2550 00002E35 F3AB                <1> 	rep	stosd
  2551 00002E37 58                  <1> 	pop	eax
  2552 00002E38 59                  <1> 	pop	ecx
  2553 00002E39 5F                  <1> 	pop	edi
  2554                              <1> mkpd_error:
  2555                              <1> mkpt_error:
  2556 00002E3A C3                  <1> 	retn
  2557                              <1> 
  2558                              <1> make_page_table:
  2559                              <1> 	; 23/06/2015
  2560                              <1> 	; 18/04/2015
  2561                              <1> 	; 12/04/2015
  2562                              <1> 	; 16/10/2014
  2563                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2564                              <1> 	;
  2565                              <1> 	; INPUT ->
  2566                              <1> 	;	EBX = virtual (linear) address
  2567                              <1> 	;	ECX = page table 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> 	;	EDX = Page directory entry address
  2573                              <1> 	;	EAX = Page table address
  2574                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2575                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2576                              <1> 	;
  2577                              <1> 	; Modified Registers -> EAX, EDX
  2578                              <1> 	;
  2579 00002E3B E878FFFFFF          <1> 	call	allocate_page
  2580 00002E40 72F8                <1> 	jc	short mkpt_error
  2581 00002E42 E811000000          <1> 	call	set_pde	
  2582 00002E47 EBE0                <1> 	jmp	short clear_page
  2583                              <1> 
  2584                              <1> make_page:
  2585                              <1> 	; 24/07/2015
  2586                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2587                              <1> 	;
  2588                              <1> 	; INPUT ->
  2589                              <1> 	;	EBX = virtual (linear) address
  2590                              <1> 	;	ECX = page attributes (lower 12 bits)
  2591                              <1> 	;	      (higher 20 bits must be ZERO)
  2592                              <1> 	;	      (bit 0 must be 1)	 
  2593                              <1> 	;	u.pgdir = page directory (physical) address
  2594                              <1> 	; OUTPUT ->
  2595                              <1> 	;	EBX = Virtual address
  2596                              <1> 	;	(EDX = PTE value)
  2597                              <1> 	;	EAX = Physical address
  2598                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2599                              <1> 	;
  2600                              <1> 	; Modified Registers -> EAX, EDX
  2601                              <1> 	;
  2602 00002E49 E86AFFFFFF          <1> 	call	allocate_page
  2603 00002E4E 7207                <1> 	jc	short mkp_err
  2604 00002E50 E821000000          <1> 	call	set_pte	
  2605 00002E55 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2606                              <1> mkp_err:
  2607 00002E57 C3                  <1> 	retn
  2608                              <1> 
  2609                              <1> set_pde:	; Set page directory entry (PDE)
  2610                              <1> 	; 20/07/2015
  2611                              <1> 	; 18/04/2015
  2612                              <1> 	; 12/04/2015
  2613                              <1> 	; 23/10/2014
  2614                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2615                              <1> 	;
  2616                              <1> 	; INPUT ->
  2617                              <1> 	;	EAX = physical address
  2618                              <1> 	;	      (use present value if EAX = 0)
  2619                              <1> 	;	EBX = virtual (linear) address
  2620                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2621                              <1> 	;	      (higher 20 bits must be ZERO)
  2622                              <1> 	;	      (bit 0 must be 1)	 
  2623                              <1> 	;	u.pgdir = page directory (physical) address
  2624                              <1> 	; OUTPUT ->
  2625                              <1> 	;	EDX = PDE address
  2626                              <1> 	;	EAX = page table address (physical)
  2627                              <1> 	;	;(CF=1 -> Invalid page address)
  2628                              <1> 	;
  2629                              <1> 	; Modified Registers -> EDX
  2630                              <1> 	;
  2631 00002E58 89DA                <1> 	mov	edx, ebx
  2632 00002E5A C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2633 00002E5D C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2634 00002E60 0315[116F0000]      <1> 	add	edx, [u.pgdir]
  2635                              <1> 	;
  2636 00002E66 21C0                <1> 	and	eax, eax
  2637 00002E68 7506                <1> 	jnz	short spde_1
  2638                              <1> 	;
  2639 00002E6A 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2640                              <1> 	;test	al, 1
  2641                              <1> 	;jz	short spde_2
  2642 00002E6C 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2643                              <1> spde_1:
  2644                              <1> 	;and	cx, 0FFFh
  2645 00002E70 8902                <1> 	mov	[edx], eax
  2646 00002E72 66090A              <1> 	or	[edx], cx
  2647 00002E75 C3                  <1> 	retn
  2648                              <1> ;spde_2: ; error
  2649                              <1> ;	stc
  2650                              <1> ;	retn
  2651                              <1> 
  2652                              <1> set_pte:	; Set page table entry (PTE)
  2653                              <1> 	; 24/07/2015
  2654                              <1> 	; 20/07/2015
  2655                              <1> 	; 23/06/2015
  2656                              <1> 	; 18/04/2015
  2657                              <1> 	; 12/04/2015
  2658                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2659                              <1> 	;
  2660                              <1> 	; INPUT ->
  2661                              <1> 	;	EAX = physical page address
  2662                              <1> 	;	      (use present value if EAX = 0)
  2663                              <1> 	;	EBX = virtual (linear) address
  2664                              <1> 	;	ECX = page attributes (lower 12 bits)
  2665                              <1> 	;	      (higher 20 bits must be ZERO)
  2666                              <1> 	;	      (bit 0 must be 1)	 
  2667                              <1> 	;	u.pgdir = page directory (physical) address
  2668                              <1> 	; OUTPUT ->
  2669                              <1> 	;	EAX = physical page address
  2670                              <1> 	;	(EDX = PTE value)
  2671                              <1> 	;	EBX = virtual address
  2672                              <1> 	;
  2673                              <1> 	;	CF = 1 -> error
  2674                              <1> 	;
  2675                              <1> 	; Modified Registers -> EAX, EDX
  2676                              <1> 	;
  2677 00002E76 50                  <1> 	push	eax
  2678 00002E77 A1[116F0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2679 00002E7C E837000000          <1> 	call 	get_pde
  2680                              <1> 		; EDX = PDE address
  2681                              <1> 		; EAX = PDE value
  2682 00002E81 5A                  <1> 	pop	edx ; physical page address
  2683 00002E82 722A                <1> 	jc	short spte_err ; PDE not present
  2684                              <1> 	;
  2685 00002E84 53                  <1> 	push	ebx ; 24/07/2015
  2686 00002E85 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2687                              <1> 			    ; EDX = PT address (physical)	
  2688 00002E89 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2689 00002E8C 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2690                              <1> 			 ; clear higher 10 bits (PD bits)
  2691 00002E92 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2692 00002E95 01C3                <1> 	add	ebx, eax
  2693                              <1> 	;
  2694 00002E97 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2695 00002E99 A801                <1> 	test	al, 1
  2696 00002E9B 740C                <1> 	jz	short spte_0
  2697 00002E9D 09D2                <1> 	or	edx, edx
  2698 00002E9F 750F                <1> 	jnz	short spte_1
  2699 00002EA1 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2700 00002EA5 89C2                <1> 	mov	edx, eax
  2701 00002EA7 EB09                <1> 	jmp	short spte_2	
  2702                              <1> spte_0:
  2703                              <1> 	; If this PTE contains a swap (disk) address,
  2704                              <1> 	; it can be updated by using 'swap_in' procedure
  2705                              <1> 	; only!
  2706 00002EA9 21C0                <1> 	and	eax, eax
  2707 00002EAB 7403                <1> 	jz	short spte_1
  2708                              <1> 	; 24/07/2015
  2709                              <1> 	; swapped page ! (on disk)
  2710 00002EAD 5B                  <1> 	pop	ebx
  2711                              <1> spte_err:
  2712 00002EAE F9                  <1> 	stc
  2713 00002EAF C3                  <1> 	retn
  2714                              <1> spte_1: 
  2715 00002EB0 89D0                <1> 	mov	eax, edx
  2716                              <1> spte_2:
  2717 00002EB2 09CA                <1> 	or	edx, ecx
  2718                              <1> 	; 23/06/2015
  2719 00002EB4 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2720                              <1> 	; 24/07/2015
  2721 00002EB6 5B                  <1> 	pop	ebx
  2722 00002EB7 C3                  <1> 	retn
  2723                              <1> 
  2724                              <1> get_pde:	; Get present value of the relevant PDE
  2725                              <1> 	; 20/07/2015
  2726                              <1> 	; 18/04/2015
  2727                              <1> 	; 12/04/2015
  2728                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2729                              <1> 	;
  2730                              <1> 	; INPUT ->
  2731                              <1> 	;	EBX = virtual (linear) address
  2732                              <1> 	;	EAX = page directory (physical) address
  2733                              <1> 	; OUTPUT ->
  2734                              <1> 	;	EDX = Page directory entry address
  2735                              <1> 	;	EAX = Page directory entry value
  2736                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2737                              <1> 	; Modified Registers -> EDX, EAX
  2738                              <1> 	;
  2739 00002EB8 89DA                <1> 	mov	edx, ebx
  2740 00002EBA C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2741 00002EBD C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2742 00002EC0 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2743 00002EC2 8B02                <1> 	mov	eax, [edx]
  2744 00002EC4 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2745 00002EC6 751F                <1> 	jnz	short gpte_retn
  2746 00002EC8 F9                  <1> 	stc
  2747                              <1> gpde_retn:	
  2748 00002EC9 C3                  <1> 	retn
  2749                              <1> 
  2750                              <1> get_pte:
  2751                              <1> 		; Get present value of the relevant PTE
  2752                              <1> 	; 29/07/2015
  2753                              <1> 	; 20/07/2015
  2754                              <1> 	; 18/04/2015
  2755                              <1> 	; 12/04/2015
  2756                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2757                              <1> 	;
  2758                              <1> 	; INPUT ->
  2759                              <1> 	;	EBX = virtual (linear) address
  2760                              <1> 	;	EAX = page directory (physical) address
  2761                              <1> 	; OUTPUT ->
  2762                              <1> 	;	EDX = Page table entry address (if CF=0)
  2763                              <1> 	;	      Page directory entry address (if CF=1)
  2764                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2765                              <1> 	;	EAX = Page table entry value (page address)
  2766                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2767                              <1> 	; Modified Registers -> EAX, EDX
  2768                              <1> 	;
  2769 00002ECA E8E9FFFFFF          <1> 	call 	get_pde
  2770 00002ECF 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2771                              <1> 	;jnc	short gpte_1
  2772                              <1> 	;retn
  2773                              <1> ;gpte_1:
  2774 00002ED1 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2775 00002ED5 89DA                <1> 	mov	edx, ebx
  2776 00002ED7 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2777 00002EDA 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2778                              <1> 			 ; clear higher 10 bits (PD bits)
  2779 00002EE0 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2780 00002EE3 01C2                <1> 	add	edx, eax
  2781 00002EE5 8B02                <1> 	mov	eax, [edx]
  2782                              <1> gpte_retn:
  2783 00002EE7 C3                  <1> 	retn
  2784                              <1> 
  2785                              <1> deallocate_page_dir:
  2786                              <1> 	; 15/09/2015
  2787                              <1> 	; 05/08/2015
  2788                              <1> 	; 30/04/2015
  2789                              <1> 	; 28/04/2015
  2790                              <1> 	; 17/10/2014
  2791                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2792                              <1> 	;
  2793                              <1> 	; INPUT ->
  2794                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2795                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2796                              <1> 	; OUTPUT ->
  2797                              <1> 	;	All of page tables in the page directory
  2798                              <1> 	;	and page dir's itself will be deallocated
  2799                              <1> 	;	except 'read only' duplicated pages (will be converted
  2800                              <1> 	;	to writable pages).
  2801                              <1> 	;
  2802                              <1> 	; Modified Registers -> EAX
  2803                              <1> 	;
  2804                              <1> 	;
  2805 00002EE8 56                  <1> 	push	esi
  2806 00002EE9 51                  <1> 	push	ecx
  2807 00002EEA 50                  <1> 	push	eax
  2808 00002EEB 89C6                <1> 	mov	esi, eax 
  2809 00002EED 31C9                <1> 	xor	ecx, ecx
  2810                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2811                              <1> 	; it must not be deallocated
  2812 00002EEF 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2813                              <1> dapd_0:
  2814 00002EF1 AD                  <1> 	lodsd
  2815 00002EF2 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2816 00002EF4 7409                <1> 	jz	short dapd_1	
  2817 00002EF6 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2818 00002EFA E812000000          <1> 	call	deallocate_page_table			
  2819                              <1> dapd_1:
  2820 00002EFF 41                  <1> 	inc	ecx ; page directory entry index
  2821 00002F00 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2822 00002F06 72E9                <1> 	jb	short dapd_0
  2823                              <1> dapd_2:
  2824 00002F08 58                  <1> 	pop	eax
  2825 00002F09 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2826 00002F0E 59                  <1> 	pop	ecx
  2827 00002F0F 5E                  <1> 	pop	esi
  2828 00002F10 C3                  <1> 	retn
  2829                              <1> 
  2830                              <1> deallocate_page_table:
  2831                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2832                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2833                              <1> 	; 19/09/2015
  2834                              <1> 	; 15/09/2015
  2835                              <1> 	; 05/08/2015
  2836                              <1> 	; 30/04/2015
  2837                              <1> 	; 28/04/2015
  2838                              <1> 	; 24/10/2014
  2839                              <1> 	; 23/10/2014
  2840                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2841                              <1> 	;
  2842                              <1> 	; INPUT ->
  2843                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2844                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2845                              <1> 	;	(ECX = page directory entry index)
  2846                              <1> 	; OUTPUT ->
  2847                              <1> 	;	All of pages in the page table and page table's itself
  2848                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2849                              <1> 	;	(will be converted to writable pages).
  2850                              <1> 	;
  2851                              <1> 	; Modified Registers -> EAX
  2852                              <1> 	;
  2853 00002F11 56                  <1> 	push	esi
  2854 00002F12 57                  <1> 	push	edi
  2855 00002F13 52                  <1> 	push	edx
  2856 00002F14 50                  <1> 	push	eax ; *
  2857 00002F15 89C6                <1> 	mov	esi, eax 
  2858 00002F17 31FF                <1> 	xor	edi, edi ; 0
  2859                              <1> dapt_0:
  2860 00002F19 AD                  <1> 	lodsd
  2861 00002F1A A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2862 00002F1C 7455                <1> 	jz	short dapt_1
  2863                              <1> 	;
  2864 00002F1E A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2865                              <1> 				  ; (must be 1)
  2866 00002F20 753F                <1> 	jnz	short dapt_3
  2867                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2868 00002F22 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2869                              <1> 				   ; as child's page ?
  2870 00002F26 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2871                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2872                              <1> 	; ECX = page directory entry index (0-1023)
  2873 00002F28 53                  <1> 	push	ebx
  2874 00002F29 51                  <1> 	push	ecx
  2875 00002F2A 66C1E102            <1> 	shl	cx, 2 ; *4 
  2876 00002F2E 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2877 00002F30 8B0B                <1> 	mov	ecx, [ebx]
  2878 00002F32 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2879 00002F35 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2880 00002F37 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2881                              <1> 	; EDI = page table entry index (0-1023)
  2882 00002F3C 89FA                <1> 	mov	edx, edi 
  2883 00002F3E 66C1E202            <1> 	shl	dx, 2 ; *4 
  2884 00002F42 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2885 00002F44 8B1A                <1> 	mov	ebx, [edx]
  2886 00002F46 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2887 00002F49 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2888 00002F4B 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2889 00002F4F 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2890 00002F54 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2891 00002F56 7507                <1> 	jne	short dapt_2	; not same page
  2892                              <1> 				; deallocate the child's page
  2893 00002F58 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2894 00002F5B 59                  <1> 	pop	ecx
  2895 00002F5C 5B                  <1> 	pop	ebx
  2896 00002F5D EB0D                <1> 	jmp	short dapt_4
  2897                              <1> 
  2898                              <1> ; 24/12/2021
  2899                              <1> ; ('dapt_1' is disabled)
  2900                              <1> ;
  2901                              <1> ;dapt_1:
  2902                              <1> ;	or	eax, eax	; swapped page ?
  2903                              <1> ;	jz	short dapt_5	; no
  2904                              <1> ;				; yes
  2905                              <1> ;	shr	eax, 1
  2906                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2907                              <1> ;				  ; on the swap disk (or in file)
  2908                              <1> ;	jmp	short dapt_5
  2909                              <1> dapt_2:
  2910 00002F5F 59                  <1> 	pop	ecx
  2911 00002F60 5B                  <1> 	pop	ebx
  2912                              <1> dapt_3:	
  2913                              <1> 	; 12/07/2016
  2914 00002F61 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2915 00002F65 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2916                              <1> 	;
  2917                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2918 00002F67 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2919                              <1> dapt_4:
  2920 00002F6C C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2921                              <1> dapt_1:	; 24/12/2021
  2922                              <1> dapt_5:
  2923 00002F73 47                  <1> 	inc	edi ; page table entry index
  2924 00002F74 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2925 00002F7A 729D                <1> 	jb	short dapt_0
  2926                              <1> 	;
  2927 00002F7C 58                  <1> 	pop	eax ; *
  2928 00002F7D 5A                  <1> 	pop	edx
  2929 00002F7E 5F                  <1> 	pop	edi	
  2930 00002F7F 5E                  <1> 	pop	esi
  2931                              <1> 	;
  2932                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2933                              <1> 	;retn
  2934                              <1> 
  2935                              <1> deallocate_page:
  2936                              <1> 	; 15/09/2015
  2937                              <1> 	; 28/04/2015
  2938                              <1> 	; 10/03/2015
  2939                              <1> 	; 17/10/2014
  2940                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2941                              <1> 	;
  2942                              <1> 	; INPUT -> 
  2943                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2944                              <1> 	; OUTPUT ->
  2945                              <1> 	;	[free_pages] is increased
  2946                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2947                              <1> 	;	CF = 1 if the page is already deallocated
  2948                              <1> 	; 	       (or not allocated) before.  
  2949                              <1> 	;
  2950                              <1> 	; Modified Registers -> EAX
  2951                              <1> 	;
  2952 00002F80 53                  <1> 	push	ebx
  2953 00002F81 52                  <1> 	push	edx
  2954                              <1> 	;
  2955 00002F82 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2956                              <1> 				     ; 12 bits right
  2957                              <1> 				     ; to get page number
  2958 00002F85 89C2                <1> 	mov	edx, eax
  2959                              <1> 	; 15/09/2015
  2960 00002F87 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2961                              <1> 				     ; (1 allocation bit = 1 page)
  2962                              <1> 				     ; (1 allocation bytes = 8 pages)
  2963 00002F8A 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2964                              <1> 				     ; (to get 32 bit position)			
  2965                              <1> 	;
  2966 00002F8D BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2967 00002F92 01D3                <1> 	add	ebx, edx
  2968 00002F94 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2969                              <1> 				     ; (allocation bit position)	 
  2970 00002F97 3B15[046B0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2971                              <1> 				     ; than the address in 'next_page' ?
  2972                              <1> 				     ; (next/first free page value)		
  2973 00002F9D 7306                <1> 	jnb	short dap_1	     ; no	
  2974 00002F9F 8915[046B0000]      <1> 	mov	[next_page], edx     ; yes
  2975                              <1> dap_1:
  2976 00002FA5 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2977                              <1> 				     ; set relevant bit to 1.
  2978                              <1> 				     ; set CF to the previous bit value	
  2979                              <1> 	;cmc			     ; complement carry flag	
  2980                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2981                              <1> 				     ; if the page is already deallocated
  2982                              <1> 				     ; before.	
  2983 00002FA8 FF05[006B0000]      <1>         inc     dword [free_pages]
  2984                              <1> dap_2:
  2985 00002FAE 5A                  <1> 	pop	edx
  2986 00002FAF 5B                  <1> 	pop	ebx
  2987 00002FB0 C3                  <1> 	retn
  2988                              <1> 
  2989                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2990                              <1> ;;                                                              ;;
  2991                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2992                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2993                              <1> ;;                                                              ;;
  2994                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2995                              <1> 
  2996                              <1> ;;$Revision: 5057 $
  2997                              <1> 
  2998                              <1> 
  2999                              <1> ;;align 4
  3000                              <1> ;;proc alloc_page
  3001                              <1> 
  3002                              <1> ;;        pushfd
  3003                              <1> ;;        cli
  3004                              <1> ;;        push    ebx
  3005                              <1> ;;;//-
  3006                              <1> ;;        cmp     [pg_data.pages_free], 1
  3007                              <1> ;;        jle     .out_of_memory
  3008                              <1> ;;;//-
  3009                              <1> ;;
  3010                              <1> ;;        mov     ebx, [page_start]
  3011                              <1> ;;        mov     ecx, [page_end]
  3012                              <1> ;;.l1:
  3013                              <1> ;;        bsf     eax, [ebx];
  3014                              <1> ;;        jnz     .found
  3015                              <1> ;;        add     ebx, 4
  3016                              <1> ;;        cmp     ebx, ecx
  3017                              <1> ;;        jb      .l1
  3018                              <1> ;;        pop     ebx
  3019                              <1> ;;        popfd
  3020                              <1> ;;        xor     eax, eax
  3021                              <1> ;;        ret
  3022                              <1> ;;.found:
  3023                              <1> ;;;//-
  3024                              <1> ;;        dec     [pg_data.pages_free]
  3025                              <1> ;;        jz      .out_of_memory
  3026                              <1> ;;;//-
  3027                              <1> ;;        btr     [ebx], eax
  3028                              <1> ;;        mov     [page_start], ebx
  3029                              <1> ;;        sub     ebx, sys_pgmap
  3030                              <1> ;;        lea     eax, [eax+ebx*8]
  3031                              <1> ;;        shl     eax, 12
  3032                              <1> ;;;//-       dec [pg_data.pages_free]
  3033                              <1> ;;        pop     ebx
  3034                              <1> ;;        popfd
  3035                              <1> ;;        ret
  3036                              <1> ;;;//-
  3037                              <1> ;;.out_of_memory:
  3038                              <1> ;;        mov     [pg_data.pages_free], 1
  3039                              <1> ;;        xor     eax, eax
  3040                              <1> ;;        pop     ebx
  3041                              <1> ;;        popfd
  3042                              <1> ;;        ret
  3043                              <1> ;;;//-
  3044                              <1> ;;endp
  3045                              <1> 
  3046                              <1> duplicate_page_dir:
  3047                              <1> 	; 21/09/2015
  3048                              <1> 	; 31/08/2015
  3049                              <1> 	; 20/07/2015
  3050                              <1> 	; 28/04/2015
  3051                              <1> 	; 27/04/2015
  3052                              <1> 	; 18/04/2015
  3053                              <1> 	; 12/04/2015
  3054                              <1> 	; 18/10/2014
  3055                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3056                              <1> 	;
  3057                              <1> 	; INPUT -> 
  3058                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3059                              <1> 	;		    page directory.
  3060                              <1> 	; OUTPUT ->
  3061                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3062                              <1> 	;	       page directory.
  3063                              <1> 	;	(New page directory with new page table entries.)
  3064                              <1> 	;	(New page tables with read only copies of the parent's
  3065                              <1> 	;	pages.)
  3066                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3067                              <1> 	;
  3068                              <1> 	; Modified Registers -> none (except EAX)
  3069                              <1> 	;
  3070 00002FB1 E802FEFFFF          <1> 	call	allocate_page
  3071 00002FB6 723E                <1> 	jc	short dpd_err
  3072                              <1> 	;
  3073 00002FB8 55                  <1> 	push	ebp ; 20/07/2015
  3074 00002FB9 56                  <1> 	push	esi
  3075 00002FBA 57                  <1> 	push	edi
  3076 00002FBB 53                  <1> 	push	ebx
  3077 00002FBC 51                  <1> 	push	ecx
  3078 00002FBD 8B35[116F0000]      <1> 	mov	esi, [u.pgdir]
  3079 00002FC3 89C7                <1> 	mov	edi, eax
  3080 00002FC5 50                  <1> 	push	eax ; save child's page directory address
  3081                              <1> 	; 31/08/2015
  3082                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3083                              <1> 	; (use same system space for all user page tables) 
  3084 00002FC6 A5                  <1> 	movsd
  3085 00002FC7 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3086 00002FCC B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3087                              <1> dpd_0:	
  3088 00002FD1 AD                  <1> 	lodsd
  3089                              <1> 	;or	eax, eax
  3090                              <1>         ;jnz     short dpd_1
  3091 00002FD2 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3092 00002FD4 7508                <1> 	jnz	short dpd_1
  3093                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3094 00002FD6 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3095 00002FDC EB0F                <1> 	jmp	short dpd_2
  3096                              <1> dpd_1:	
  3097 00002FDE 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3098 00002FE2 89C3                <1> 	mov	ebx, eax
  3099                              <1> 	; EBX = Parent's page table address
  3100 00002FE4 E81F000000          <1> 	call	duplicate_page_table
  3101 00002FE9 720C                <1> 	jc	short dpd_p_err
  3102                              <1> 	; EAX = Child's page table address
  3103 00002FEB 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3104                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3105                              <1> 			 ; (present, writable, user)
  3106                              <1> dpd_2:
  3107 00002FED AB                  <1> 	stosd
  3108 00002FEE E2E1                <1> 	loop	dpd_0
  3109                              <1> 	;
  3110 00002FF0 58                  <1> 	pop	eax  ; restore child's page directory address
  3111                              <1> dpd_3:
  3112 00002FF1 59                  <1> 	pop	ecx
  3113 00002FF2 5B                  <1> 	pop	ebx
  3114 00002FF3 5F                  <1> 	pop	edi
  3115 00002FF4 5E                  <1> 	pop	esi
  3116 00002FF5 5D                  <1> 	pop	ebp ; 20/07/2015
  3117                              <1> dpd_err:
  3118 00002FF6 C3                  <1> 	retn
  3119                              <1> dpd_p_err:
  3120                              <1> 	; release the allocated pages missing (recover free space)
  3121 00002FF7 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3122 00002FF8 8B1D[116F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3123 00002FFE E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3124 00003003 29C0                <1> 	sub	eax, eax ; 0
  3125 00003005 F9                  <1> 	stc
  3126 00003006 EBE9                <1> 	jmp	short dpd_3	
  3127                              <1> 
  3128                              <1> duplicate_page_table:
  3129                              <1> 	; 31/12/2021
  3130                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3131                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3132                              <1> 	; 21/09/2015
  3133                              <1> 	; 20/07/2015
  3134                              <1> 	; 05/05/2015
  3135                              <1> 	; 28/04/2015
  3136                              <1> 	; 27/04/2015
  3137                              <1> 	; 18/04/2015
  3138                              <1> 	; 18/10/2014
  3139                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3140                              <1> 	;
  3141                              <1> 	; INPUT -> 
  3142                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3143                              <1> 	;       20/02/2017		 
  3144                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3145                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3146                              <1> 	; OUTPUT ->
  3147                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3148                              <1> 	;	      (with 'read only' attribute of page table entries)
  3149                              <1> 	;	20/02/2017
  3150                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3151                              <1> 	;	
  3152                              <1> 	;	CF = 1 -> error 
  3153                              <1> 	;
  3154                              <1> 	; Modified Registers -> EBP (except EAX)
  3155                              <1> 	;
  3156 00003008 E8ABFDFFFF          <1> 	call	allocate_page
  3157 0000300D 725B                <1> 	jc	short dpt_err
  3158                              <1> 	;
  3159 0000300F 50                  <1> 	push	eax ; *
  3160 00003010 56                  <1> 	push	esi
  3161 00003011 57                  <1> 	push	edi
  3162 00003012 52                  <1> 	push	edx
  3163 00003013 51                  <1> 	push	ecx
  3164                              <1> 	;
  3165 00003014 89DE                <1> 	mov	esi, ebx
  3166 00003016 89C7                <1> 	mov	edi, eax
  3167 00003018 89C2                <1> 	mov	edx, eax
  3168 0000301A 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3169                              <1> dpt_0:
  3170 00003020 AD                  <1> 	lodsd
  3171 00003021 21C0                <1> 	and	eax, eax
  3172 00003023 7435                <1> 	jz	short dpt_3
  3173 00003025 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3174                              <1> 	; 24/12/2021
  3175 00003027 7503                <1> 	jnz	short dpt_1
  3176                              <1> 	;jz	short dpt_p_err
  3177                              <1> 	; 31/12/2021
  3178 00003029 F9                  <1> 	stc
  3179 0000302A EB39                <1> 	jmp	short dpt_p_err
  3180                              <1> 
  3181                              <1> ; 24/12/2021
  3182                              <1> ; ('reload_page' procedure call is disabled)
  3183                              <1> ;
  3184                              <1> ;	; 20/07/2015
  3185                              <1> ;	; ebp = virtual (linear) address of the memory page
  3186                              <1> ;	call	reload_page ; 28/04/2015
  3187                              <1> ;	jc	short dpt_p_err
  3188                              <1> dpt_1:
  3189                              <1> 	; 21/09/2015
  3190 0000302C 89C1                <1> 	mov	ecx, eax
  3191 0000302E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3192 00003032 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3193 00003035 751A                <1> 	jnz	short dpt_2
  3194                              <1> 	; Read only (parent) page
  3195                              <1> 	; 	- there is a third process which uses this page -
  3196                              <1> 	; Allocate a new page for the child process
  3197 00003037 E87CFDFFFF          <1> 	call	allocate_page
  3198 0000303C 7227                <1> 	jc	short dpt_p_err
  3199 0000303E 57                  <1> 	push	edi
  3200 0000303F 56                  <1> 	push	esi
  3201 00003040 89CE                <1> 	mov	esi, ecx
  3202 00003042 89C7                <1> 	mov	edi, eax
  3203 00003044 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3204 00003049 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3205 0000304B 5E                  <1> 	pop	esi
  3206 0000304C 5F                  <1> 	pop	edi
  3207                              <1> 	;
  3208                              <1> 
  3209                              <1> ; 24/12/2021
  3210                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3211                              <1> ; 
  3212                              <1> ;	push	ebx
  3213                              <1> ;	push	eax
  3214                              <1> ;	; 20/07/2015
  3215                              <1> ;	mov	ebx, ebp
  3216                              <1> ;	; ebx = virtual (linear) address of the memory page
  3217                              <1> ;	call	add_to_swap_queue
  3218                              <1> ;	pop	eax
  3219                              <1> ;	pop	ebx
  3220                              <1> 
  3221                              <1> 	; 21/09/2015
  3222 0000304D 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3223                              <1> 		; user + writable + present page
  3224 0000304F EB09                <1> 	jmp	short dpt_3
  3225                              <1> dpt_2:
  3226                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3227 00003051 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3228                              <1> 		    ; (read only page!)
  3229 00003053 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3230 00003056 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3231                              <1> dpt_3:
  3232 0000305A AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3233                              <1> 	;
  3234 0000305B 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3235                              <1> 	;
  3236 00003061 39D7                <1> 	cmp	edi, edx
  3237 00003063 72BB                <1> 	jb	short dpt_0
  3238                              <1> dpt_p_err:
  3239 00003065 59                  <1> 	pop	ecx
  3240 00003066 5A                  <1> 	pop	edx
  3241 00003067 5F                  <1> 	pop	edi
  3242 00003068 5E                  <1> 	pop	esi
  3243 00003069 58                  <1> 	pop	eax ; *
  3244                              <1> dpt_err:
  3245 0000306A C3                  <1> 	retn
  3246                              <1> 
  3247                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3248                              <1> 	; 31/12/2021
  3249                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3250                              <1> 	; 21/09/2015
  3251                              <1> 	; 19/09/2015
  3252                              <1> 	; 17/09/2015
  3253                              <1> 	; 28/08/2015
  3254                              <1> 	; 20/07/2015
  3255                              <1> 	; 28/06/2015
  3256                              <1> 	; 03/05/2015
  3257                              <1> 	; 30/04/2015
  3258                              <1> 	; 18/04/2015
  3259                              <1> 	; 12/04/2015
  3260                              <1> 	; 30/10/2014
  3261                              <1> 	; 11/09/2014
  3262                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3263                              <1> 	;
  3264                              <1> 	; Note: This is not an interrupt/exception handler.
  3265                              <1> 	;	This is a 'page fault remedy' subroutine 
  3266                              <1> 	;	which will be called by standard/uniform
  3267                              <1> 	;	exception handler.
  3268                              <1> 	;
  3269                              <1> 	; INPUT -> 
  3270                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3271                              <1> 	;
  3272                              <1> 	;	cr2 = the virtual (linear) address 
  3273                              <1> 	;	      which has caused to page fault (19/09/2015)
  3274                              <1> 	;
  3275                              <1> 	; OUTPUT ->
  3276                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3277                              <1> 	;	EAX = 0 -> no error
  3278                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3279                              <1> 	;
  3280                              <1> 	; Modified Registers -> none (except EAX)
  3281                              <1> 	;	
  3282                              <1>         ;
  3283                              <1>         ; ERROR CODE:
  3284                              <1> 	;	 31  .....	4   3	2   1	0
  3285                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3286                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3287                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3288                              <1> 	;
  3289                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3290                              <1>     	;		a page-protection violation. When not set,
  3291                              <1> 	;		it was caused by a non-present page.
  3292                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3293                              <1> 	;		a page write. When not set, it was caused
  3294                              <1> 	;		by a page read.
  3295                              <1> 	; U : USER    -	When set, the page fault was caused 
  3296                              <1> 	;		while CPL = 3. 
  3297                              <1> 	;		This does not necessarily mean that
  3298                              <1> 	;		the page fault was a privilege violation.
  3299                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3300                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3301                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3302                              <1> 	;     FETCH	an instruction fetch
  3303                              <1> 	;
  3304                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3305                              <1> 	;  31               22                  12 11                    0
  3306                              <1> 	; +-------------------+-------------------+-----------------------+
  3307                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3308                              <1>        	; +-------------------+-------------------+-----------------------+
  3309                              <1> 	;
  3310                              <1> 
  3311                              <1> 	;; CR3 REGISTER (Control Register 3)
  3312                              <1> 	;  31                                   12             5 4 3 2   0
  3313                              <1> 	; +---------------------------------------+-------------+---+-----+
  3314                              <1>       	; |                                       |  		|P|P|     |
  3315                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3316                              <1>       	; |                                       | 		|D|T|     |
  3317                              <1>    	; +---------------------------------------+-------------+---+-----+
  3318                              <1> 	;
  3319                              <1> 	;	PWT    - WRITE THROUGH
  3320                              <1> 	;	PCD    - CACHE DISABLE		
  3321                              <1> 	;
  3322                              <1> 	;
  3323                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3324                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3325                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3326                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3327                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3328                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3329                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3330                              <1> 	;
  3331                              <1>         ;       P      - PRESENT
  3332                              <1>         ;       R/W    - READ/WRITE
  3333                              <1>         ;       U/S    - USER/SUPERVISOR
  3334                              <1> 	;	PWT    - WRITE THROUGH
  3335                              <1> 	;	PCD    - CACHE DISABLE	
  3336                              <1> 	;	A      - ACCESSED	
  3337                              <1>         ;       D      - DIRTY (IGNORED)
  3338                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3339                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3340                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3341                              <1> 	;
  3342                              <1> 	;
  3343                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3344                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3345                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3346                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3347                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3348                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3349                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3350                              <1> 	;
  3351                              <1>         ;       P      - PRESENT
  3352                              <1>         ;       R/W    - READ/WRITE
  3353                              <1>         ;       U/S    - USER/SUPERVISOR
  3354                              <1> 	;	PWT    - WRITE THROUGH
  3355                              <1> 	;	PCD    - CACHE DISABLE	
  3356                              <1> 	;	A      - ACCESSED	
  3357                              <1>         ;       D      - DIRTY
  3358                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3359                              <1> 	;	G      - GLOBAL	 
  3360                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3361                              <1> 	;
  3362                              <1> 	;
  3363                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3364                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3365                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3366                              <1>       	; |                                       |     | | | | | | |U|R| |
  3367                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3368                              <1>       	; |                                       |     | | | | | | |S|W| |
  3369                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3370                              <1> 	;
  3371                              <1>         ;       P      - PRESENT
  3372                              <1>         ;       R/W    - READ/WRITE
  3373                              <1>         ;       U/S    - USER/SUPERVISOR
  3374                              <1>         ;       D      - DIRTY
  3375                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3376                              <1> 	;
  3377                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3378                              <1> 	;
  3379                              <1> 	;
  3380                              <1> 	;; Invalid Page Table Entry
  3381                              <1> 	; 31                                                           1 0
  3382                              <1>       	; +-------------------------------------------------------------+-+
  3383                              <1>       	; |                                                             | |
  3384                              <1>       	; |                          AVAILABLE                          |0|
  3385                              <1>       	; |                                                             | |
  3386                              <1>       	; +-------------------------------------------------------------+-+
  3387                              <1> 	;
  3388                              <1> 
  3389 0000306B 53                  <1> 	push	ebx
  3390 0000306C 52                  <1> 	push	edx
  3391 0000306D 51                  <1> 	push	ecx
  3392                              <1> 	;
  3393                              <1> 	; 21/09/2015 (debugging)
  3394 0000306E FF05[216F0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3395 00003074 FF05[B06B0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3396                              <1> 	; 28/06/2015
  3397                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3398 0000307A 8A15[A86B0000]      <1> 	mov	dl, [error_code]
  3399                              <1> 	;
  3400 00003080 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3401                              <1> 			; sign
  3402 00003083 7425                <1> 	jz	short pfh_alloc_np
  3403                              <1> 	; 
  3404                              <1> 	; If it is not a 'write on read only page' type page fault
  3405                              <1> 	; major page fault error with minor reason must be returned without 
  3406                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3407                              <1> 	; after return here!
  3408                              <1> 	; Page fault will be remedied, by copying page contents
  3409                              <1> 	; to newly allocated page with write permission;
  3410                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3411                              <1> 	; used for working with minimum possible memory usage. 
  3412                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3413                              <1> 	; process with 'read only' flag. If the child process attempts to
  3414                              <1> 	; write on these read only pages, page fault will be directed here
  3415                              <1> 	; for allocating a new page with same data/content. 
  3416                              <1> 	;
  3417                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3418                              <1> 	; will not force to separate CODE and DATA space 
  3419                              <1> 	; in a process/program... 
  3420                              <1> 	; CODE segment/section may contain DATA!
  3421                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3422                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3423                              <1> 	;	
  3424 00003085 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3425                              <1> 			; sign
  3426 00003088 7418                <1>         jz      pfh_p_err
  3427                              <1> 	; 31/08/2015
  3428 0000308A F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3429                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3430 0000308D 7413                <1>         jz	short pfh_pv_err
  3431                              <1> 	;
  3432                              <1> 	; make a new page and copy the parent's page content
  3433                              <1> 	; as the child's new page content
  3434                              <1> 	;
  3435 0000308F 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3436                              <1> 			 ; which has caused to page fault
  3437 00003092 E87C000000          <1> 	call 	copy_page
  3438 00003097 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3439                              <1> 	;
  3440 00003099 EB72                <1>         jmp     pfh_cpp_ok
  3441                              <1> 
  3442                              <1> 	; 31/12/2021 (short jump)
  3443                              <1> pfh_im_err:
  3444 0000309B B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3445                              <1> 			; Major (Primary) Error: Page Fault
  3446                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3447 000030A0 EB6D                <1> 	jmp	short pfh_err_retn
  3448                              <1> 
  3449                              <1> 	; 31/12/2021
  3450                              <1> pfh_p_err: ; 09/03/2015
  3451                              <1> pfh_pv_err:
  3452                              <1> 	; Page fault was caused by a protection-violation
  3453 000030A2 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3454                              <1> 			; Major (Primary) Error: Page Fault
  3455                              <1> 			; Minor (Secondary) Error: Protection violation !
  3456 000030A7 F9                  <1> 	stc
  3457 000030A8 EB65                <1> 	jmp	short pfh_err_retn
  3458                              <1> 	
  3459                              <1> pfh_alloc_np:
  3460 000030AA E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3461 000030AF 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3462                              <1> pfh_chk_cpl:
  3463                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3464                              <1> 		; (Lower 12 bits are ZERO, because 
  3465                              <1> 		;	the address is on a page boundary)
  3466 000030B1 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3467 000030B4 7505                <1> 	jnz	short pfh_um
  3468                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3469 000030B6 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3470                              <1> 			 ; of the current/active page directory
  3471                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3472                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3473 000030B9 EB06                <1> 	jmp	short pfh_get_pde
  3474                              <1> 	;
  3475                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3476 000030BB 8B1D[116F0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3477                              <1> 			; Physical address of the USER's page directory
  3478                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3479                              <1> pfh_get_pde:
  3480 000030C1 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3481 000030C4 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3482                              <1> 			 ; which has been caused to page fault
  3483                              <1> 			 ;
  3484 000030C7 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3485 000030CA 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3486                              <1> 	;
  3487 000030CD 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3488 000030CF 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3489 000030D1 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3490 000030D4 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3491                              <1> 			  	  ; set/validate page directory entry
  3492 000030D6 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3493 000030DB 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3494 000030DD 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3495 000030DF EB16                <1> 	jmp	short pfh_get_pte
  3496                              <1> pfh_set_pde:
  3497                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3498                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3499                              <1> 	;
  3500 000030E1 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3501 000030E3 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3502 000030E5 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3503 000030E7 89C3                <1> 	mov	ebx, eax
  3504 000030E9 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3505 000030EE 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3506                              <1> pfh_spde_1:
  3507                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3508 000030F0 89C1                <1> 	mov	ecx, eax
  3509 000030F2 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3510                              <1> pfh_get_pte:
  3511 000030F7 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3512                              <1> 			 ; which has been caused to page fault
  3513 000030FA 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3514 000030FC C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3515                              <1> 			 ; higher 20 bits of the page fault address 
  3516 000030FF 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3517 00003104 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3518 00003107 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3519                              <1> ; 24/12/2021
  3520                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3521                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3522                              <1> ; 24/12/2021
  3523                              <1> ; ('swap_in' procedure call has been disabled)
  3524                              <1> ;
  3525                              <1> ;	and	eax, eax
  3526                              <1> ;	jz	short pfh_gpte_1
  3527                              <1> ;	; 20/07/2015
  3528                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3529                              <1> ;	push	ebp ; 20/07/2015
  3530                              <1> ;	mov	ebp, cr2
  3531                              <1> ;		; ECX = physical address of the page table entry
  3532                              <1> ;		; EBX = Memory page address (physical!)
  3533                              <1> ;		; EAX = Swap disk (offset) address
  3534                              <1> ;		; EBP = virtual address (page fault address)
  3535                              <1> ;	call	swap_in
  3536                              <1> ;	pop	ebp
  3537                              <1> ;	jc      short pfh_err_retn
  3538                              <1> ;	xchg	ecx, ebx
  3539                              <1> ;		; EBX = physical address of the page table entry
  3540                              <1> ;		; ECX = new page
  3541                              <1> pfh_gpte_1:
  3542 00003109 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3543 0000310B 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3544                              <1> pfh_cpp_ok:
  3545                              <1> ; 24/12/2021
  3546                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3547                              <1> ;
  3548                              <1> ;	; 20/07/2015
  3549                              <1> ;	mov	ebx, cr2
  3550                              <1> ;	call 	add_to_swap_queue
  3551                              <1> 	;
  3552                              <1> 	; The new PTE (which contains the new page) will be added to 
  3553                              <1> 	; the swap queue, here. 
  3554                              <1> 	; (Later, if memory will become insufficient, 
  3555                              <1> 	; one page will be swapped out which is at the head of 
  3556                              <1> 	; the swap queue by using FIFO and access check methods.)
  3557                              <1> 	;
  3558 0000310D 31C0                <1> 	xor	eax, eax  ; 0
  3559                              <1> 	;
  3560                              <1> pfh_err_retn:
  3561 0000310F 59                  <1> 	pop	ecx
  3562 00003110 5A                  <1> 	pop	edx
  3563 00003111 5B                  <1> 	pop	ebx
  3564 00003112 C3                  <1> 	retn 
  3565                              <1> 	
  3566                              <1> copy_page:
  3567                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3568                              <1> 	; 16/04/2021
  3569                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3570                              <1> 	; 22/09/2015
  3571                              <1> 	; 21/09/2015
  3572                              <1> 	; 19/09/2015
  3573                              <1> 	; 07/09/2015
  3574                              <1> 	; 31/08/2015
  3575                              <1> 	; 20/07/2015
  3576                              <1> 	; 05/05/2015
  3577                              <1> 	; 03/05/2015
  3578                              <1> 	; 18/04/2015
  3579                              <1> 	; 12/04/2015
  3580                              <1> 	; 30/10/2014
  3581                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3582                              <1> 	;
  3583                              <1> 	; INPUT -> 
  3584                              <1> 	;	EBX = Virtual (linear) address of source page
  3585                              <1> 	;	     (Page fault address)
  3586                              <1> 	; OUTPUT ->
  3587                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3588                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3589                              <1> 	;	EAX = 0 (CF = 1) 
  3590                              <1> 	;		if there is not a free page to be allocated
  3591                              <1> 	;	(page content of the source page will be copied
  3592                              <1> 	;	onto the target/new page) 	
  3593                              <1> 	;
  3594                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3595                              <1> 	;
  3596                              <1> 
  3597                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3598                              <1> 	; INPUT: 
  3599                              <1> 	;	EBX = Virtual (linear) address of source page
  3600                              <1> 	;	     (Page fault address)
  3601                              <1> 	; OUTPUT:
  3602                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3603                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3604                              <1> 	;	EAX = 0 (CF = 1) 
  3605                              <1> 	;		if there is not a free page to be allocated
  3606                              <1> 	;	(page content of the source page will be copied
  3607                              <1> 	;	onto the target/new page) 	
  3608                              <1> 	;
  3609                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3610                              <1> 	
  3611 00003113 56                  <1> 	push	esi ; *
  3612 00003114 57                  <1> 	push	edi ; **
  3613                              <1> 	; 16/04/2021
  3614                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3615                              <1> 	;push	ebx ; ***
  3616                              <1> 	;push	ecx ; ****
  3617 00003115 31F6                <1> 	xor 	esi, esi
  3618 00003117 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3619 0000311A 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3620 0000311C C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3621 0000311F 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3622 00003122 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3623 00003124 031D[116F0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3624 0000312A 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3625 0000312C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3626 00003130 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3627 00003132 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3628 00003138 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3629 0000313C 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3630                              <1> 	; 07/09/2015
  3631 0000313E 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3632                              <1> 				     ; read only page as a child process?)	
  3633 00003143 7509                <1> 	jnz	short cpp_0 ; yes
  3634 00003145 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3635 00003147 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3636 0000314C EB32                <1> 	jmp	short cpp_1
  3637                              <1> cpp_0:
  3638 0000314E 89FE                <1> 	mov	esi, edi
  3639 00003150 0335[156F0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3640 00003156 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3641 00003158 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3642 0000315C 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3643 0000315E 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3644 00003164 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3645 00003168 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3646 0000316A 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3647                              <1> 	; 21/09/2015
  3648 0000316C 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3649 0000316E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3650                              <1> 	;
  3651 00003172 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3652 00003175 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3653                              <1> 	;
  3654 00003177 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3655 0000317C 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3656 0000317E 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3657                              <1> 			    ; Convert child's page to writable page
  3658                              <1> cpp_1:
  3659 00003180 E833FCFFFF          <1> 	call	allocate_page
  3660 00003185 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3661 00003187 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3662 00003189 7405                <1> 	jz	short cpp_2
  3663                              <1> 		; Convert read only page to writable page 
  3664                              <1> 		;(for the parent of the current process)
  3665                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3666                              <1> 	; 22/09/2015
  3667 0000318B 890E                <1> 	mov	[esi], ecx
  3668 0000318D 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3669                              <1> 				 ; 1+2+4 = 7
  3670                              <1> cpp_2:
  3671 00003190 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3672                              <1> 	; 07/09/2015
  3673 00003192 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3674 00003194 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3675 00003199 F3A5                <1> 	rep	movsd ; 31/08/2015
  3676                              <1> cpp_3:		
  3677 0000319B 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3678 0000319D 8903                <1> 	mov	[ebx], eax ; Update PTE
  3679 0000319F 28C0                <1> 	sub	al, al ; clear attributes
  3680                              <1> cpp_4:
  3681                              <1> 	; 16/04/2021
  3682                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3683                              <1> 	;pop	ecx ; ****
  3684                              <1> 	;pop	ebx ; ***
  3685 000031A1 5F                  <1> 	pop	edi ; **
  3686 000031A2 5E                  <1> 	pop	esi ; *
  3687 000031A3 C3                  <1> 	retn
  3688                              <1> 
  3689                              <1> ;; 28/04/2015
  3690                              <1> ;; 24/10/2014
  3691                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3692                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3693                              <1> ;;
  3694                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3695                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3696                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3697                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3698                              <1> ;;
  3699                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3700                              <1> ;;
  3701                              <1> ;; Method:
  3702                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3703                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3704                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3705                              <1> ;;	When a new page is being allocated, swap queue is updated
  3706                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3707                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3708                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3709                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3710                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3711                              <1> ;;	offset value becomes it's previous offset value - 4.
  3712                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3713                              <1> ;;	the queue/list is not shifted.
  3714                              <1> ;;	After the queue/list shift, newly allocated page is added
  3715                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3716                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3717                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3718                              <1> ;;	
  3719                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3720                              <1> ;;	the first non-accessed, writable page in the list, 
  3721                              <1> ;;	from the head to the tail. The list is shifted to left 
  3722                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3723                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3724                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3725                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3726                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3727                              <1> ;;	procedure will be failed)...
  3728                              <1> ;;
  3729                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3730                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3731                              <1> ;;	(PTE) will be added to the tail of the queue after
  3732                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3733                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3734                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3735                              <1> ;;
  3736                              <1> ;;
  3737                              <1> ;;	
  3738                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3739                              <1> ;;
  3740                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3741                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3742                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3743                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3744                              <1> ;;
  3745                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3746                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3747                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3748                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3749                              <1> ;; 		 (entire swap space must be accessed by using
  3750                              <1> ;;		 31 bit offset address) 
  3751                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3752                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3753                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3754                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3755                              <1> ;;
  3756                              <1> ;; 					
  3757                              <1> ;; Method:
  3758                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3759                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3760                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3761                              <1> ;;	Swapping out is performed by using swap page queue.
  3762                              <1> ;;
  3763                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3764                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3765                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3766                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3767                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3768                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3769                              <1> ;;	calculated by adding offset value to the swap partition's 
  3770                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3771                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3772                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3773                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3774                              <1> ;;	is in a partitioned virtual hard disk.) 
  3775                              <1> ;;
  3776                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3777                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3778                              <1> ;;
  3779                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3780                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3781                              <1> ;;
  3782                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3783                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3784                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3785                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3786                              <1> ;;	it means relevant (respective) block is in use, and, 
  3787                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3788                              <1> ;;      swap disk/file block is free.
  3789                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3790                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3791                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3792                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3793                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3794                              <1> ;;	------------------------------------------------------------
  3795                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3796                              <1> ;;	------------------------------------------------------------
  3797                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3798                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3799                              <1> ;;
  3800                              <1> ;;	..............................................................
  3801                              <1> ;;
  3802                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3803                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3804                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3805                              <1> ;;	position with value of 1 on the table is converted to swap
  3806                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3807                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3808                              <1> ;;	number of physical swap disk or virtual swap disk)
  3809                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3810                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3811                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3812                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3813                              <1> ;;	If disk write procedure returns with error or free count of 
  3814                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3815                              <1> ;;	'insufficient memory error' (cf=1). 
  3816                              <1> ;;
  3817                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3818                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3819                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3820                              <1> ;;	free blocks after a disk write error. It will return to 
  3821                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3822                              <1> ;;
  3823                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3824                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3825                              <1> ;;	address (cf=0). 
  3826                              <1> ;;
  3827                              <1> ;;	..............................................................
  3828                              <1> ;;
  3829                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3830                              <1> ;;	file sectors at specified memory page. Then page allocation
  3831                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3832                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3833                              <1> ;;	to do, except to terminate the process which is the owner of
  3834                              <1> ;;	the swapped page.
  3835                              <1> ;;
  3836                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3837                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3838                              <1> ;;	updates [swpd_first] pointer if it is required.
  3839                              <1> ;;
  3840                              <1> ;;	..............................................................	 
  3841                              <1> ;;
  3842                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3843                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3844                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3845                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3846                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3847                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3848                              <1> ;;
  3849                              <1> 
  3850                              <1> ; 24/12/2021
  3851                              <1> ; ('swap_in' procedure call is disabled)
  3852                              <1> 
  3853                              <1> ;swap_in:
  3854                              <1> 	; 31/08/2015
  3855                              <1> 	; 20/07/2015
  3856                              <1> 	; 28/04/2015
  3857                              <1> 	; 18/04/2015
  3858                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3859                              <1> 	;
  3860                              <1> 	; INPUT -> 
  3861                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3862                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3863                              <1> 	;	EAX = Offset Address for the swapped page on the
  3864                              <1> 	;	      swap disk or in the swap file.
  3865                              <1> 	;
  3866                              <1> 	; OUTPUT ->
  3867                              <1> 	;	EAX = 0 if loading at memory has been successful
  3868                              <1> 	;
  3869                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3870                              <1> 	;		  or sector not present or drive not ready
  3871                              <1> 	;	     EAX = Error code
  3872                              <1> 	;	     [u.error] = EAX 
  3873                              <1> 	;		       = The last error code for the process
  3874                              <1> 	;		         (will be reset after returning to user)	  
  3875                              <1> 	;
  3876                              <1> 	; Modified Registers -> EAX
  3877                              <1> 	;
  3878                              <1> 
  3879                              <1> ;       cmp     dword [swp_drv], 0
  3880                              <1> ;	jna	short swpin_dnp_err
  3881                              <1> ;
  3882                              <1> ;	cmp	eax, [swpd_size]
  3883                              <1> ;	jnb	short swpin_snp_err
  3884                              <1> ;
  3885                              <1> ;	push	esi
  3886                              <1> ;	push	ebx
  3887                              <1> ;	push	ecx
  3888                              <1> ;	mov	esi, [swp_drv]	
  3889                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3890                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3891                              <1> ;		; size different than 512 bytes, logical disk sector
  3892                              <1> ;		; size is 512 bytes and disk reading procedure
  3893                              <1> ;		; will be performed for reading 4096 bytes
  3894                              <1> ;		; (2*2048, 8*512). 
  3895                              <1> ;	; ESI = Logical disk description table address
  3896                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3897                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3898                              <1> ;	; ECX = Sector count ; 8 sectors
  3899                              <1> ;	push	eax
  3900                              <1> ;	call	logical_disk_read
  3901                              <1> ;	pop	eax
  3902                              <1> ;	jnc	short swpin_read_ok
  3903                              <1> ;	;
  3904                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3905                              <1> ;	mov	[u.error], eax
  3906                              <1> ;	jmp	short swpin_retn
  3907                              <1> ;	;
  3908                              <1> ;swpin_read_ok:
  3909                              <1> ;	; EAX = Offset address (logical sector number)
  3910                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3911                              <1> ;	;
  3912                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3913                              <1> ;	; 20/07/2015
  3914                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3915                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3916                              <1> ;	mov	bl, [u.uno] ; current process number
  3917                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3918                              <1> ;	call	swap_queue_shift
  3919                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3920                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3921                              <1> ;	; zf = 1
  3922                              <1> ;swpin_retn:
  3923                              <1> ;	pop	ecx
  3924                              <1> ;	pop	ebx
  3925                              <1> ;	pop	esi
  3926                              <1> ;	retn
  3927                              <1> ;
  3928                              <1> ;swpin_dnp_err:
  3929                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3930                              <1> ;swpin_err_retn:
  3931                              <1> ;	mov	[u.error], eax
  3932                              <1> ;	stc
  3933                              <1> ;	retn
  3934                              <1> ;
  3935                              <1> ;swpin_snp_err:
  3936                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3937                              <1> ;	jmp	short swpin_err_retn
  3938                              <1> 
  3939                              <1> ; 24/12/2021
  3940                              <1> ; ('swap_out' procedure call is disabled)
  3941                              <1> 
  3942                              <1> ;swap_out:
  3943                              <1> 	; 10/06/2016
  3944                              <1> 	; 07/06/2016
  3945                              <1>         ; 23/05/2016
  3946                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3947                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3948                              <1> 	;
  3949                              <1> 	; INPUT -> 
  3950                              <1> 	;	none
  3951                              <1> 	;
  3952                              <1> 	; OUTPUT ->
  3953                              <1> 	;	EAX = Physical page address (which is swapped out
  3954                              <1> 	;	      for allocating a new page)
  3955                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3956                              <1> 	;		  or sector not present or drive not ready
  3957                              <1> 	;	     EAX = Error code
  3958                              <1> 	;	     [u.error] = EAX 
  3959                              <1> 	;		       = The last error code for the process
  3960                              <1> 	;		         (will be reset after returning to user)	  
  3961                              <1> 	;
  3962                              <1> 	; Modified Registers -> none (except EAX)
  3963                              <1> 	;
  3964                              <1> 
  3965                              <1> ;	cmp 	word [swpq_count], 1
  3966                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3967                              <1> ;
  3968                              <1> ;       ;cmp    dword [swp_drv], 1
  3969                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3970                              <1> ;
  3971                              <1> ;       cmp     dword [swpd_free], 1
  3972                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3973                              <1> ;
  3974                              <1> ;	push	ebx ; *
  3975                              <1> ;swpout_1:
  3976                              <1> ;	; 10/06/2016
  3977                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3978                              <1> ;	call	swap_queue_shift
  3979                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3980                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3981                              <1> ;				       ; pointer in the swap queue
  3982                              <1> ;	; EAX = PTE value of the page
  3983                              <1> ;	; EBX = PTE address of the page
  3984                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3985                              <1> ;	;
  3986                              <1> ;	; 07/06/2016
  3987                              <1> ;	; 19/05/2016
  3988                              <1> ;	; check this page is in timer events or not
  3989                              <1> ;	
  3990                              <1> ;swpout_timer_page_0:
  3991                              <1> ;	push	edx ; **
  3992                              <1> ;
  3993                              <1> ;	; 07/06/2016
  3994                              <1> ;	cmp	byte [timer_events], 0 
  3995                              <1> ;	jna	short swpout_2
  3996                              <1> ;	;
  3997                              <1> ;	mov	dl, [timer_events]
  3998                              <1> ;
  3999                              <1> ;	push	ecx ; ***
  4000                              <1> ;	push	ebx ; ****
  4001                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4002                              <1> ;			       ; structures 
  4003                              <1> ;swpout_timer_page_1:
  4004                              <1> ;	mov	cl, [ebx]
  4005                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4006                              <1> ;	jz	short swpout_timer_page_3
  4007                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4008                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4009                              <1> ;				; of the response byte address, to
  4010                              <1> ;				; get beginning of the page address)
  4011                              <1> ;	cmp	eax, ecx
  4012                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4013                              <1> ;	
  4014                              <1> ;	; !same page!
  4015                              <1> ;	;
  4016                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4017                              <1> ;	; This page will be used by the kernel to put timer event
  4018                              <1> ;	; response (signal return) byte at the requested address;
  4019                              <1> ;	; in order to prevent a possible wrong write (while
  4020                              <1> ;	; this page is swapped out) on physical memory,
  4021                              <1> ;	; we must protect this page against to be swapped out!
  4022                              <1> ;	;
  4023                              <1> ;	pop	ebx ; ****
  4024                              <1> ;	pop	ecx ; ***
  4025                              <1> ;	pop	edx ; **
  4026                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4027                              <1> ; 
  4028                              <1> ;swpout_timer_page_2:
  4029                              <1> ;	; 07/06/2016
  4030                              <1> ;	dec	dl
  4031                              <1> ;	jz	short swpout_timer_page_4
  4032                              <1> ;swpout_timer_page_3:
  4033                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4034                              <1> ;	;jnb	short swpout_timer_page_4
  4035                              <1> ;	add	ebx, 16
  4036                              <1> ;	jmp	short swpout_timer_page_1	
  4037                              <1> ;
  4038                              <1> ;swpout_timer_page_4:
  4039                              <1> ;	pop	ebx ; ****
  4040                              <1> ;	pop	ecx ; ***
  4041                              <1> ;swpout_2:
  4042                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4043                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4044                              <1> ;	;
  4045                              <1> ;	call	link_swap_block
  4046                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4047                              <1> ;				       ; because [swpd_free] value
  4048                              <1> ;				       ; was checked at the beginging. 	
  4049                              <1> ;	pop	edx ; **
  4050                              <1> ;	pop	ebx ; *
  4051                              <1> ;	jmp	short swpout_nfspc_err 
  4052                              <1> ;swpout_3:
  4053                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4054                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4055                              <1> ;	;	
  4056                              <1> ;	push	esi ; **
  4057                              <1> ;	push	ecx ; ***
  4058                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4059                              <1> ;	mov	esi, [swp_drv]	
  4060                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4061                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4062                              <1> ;		; size different than 512 bytes, logical disk sector
  4063                              <1> ;		; size is 512 bytes and disk writing procedure
  4064                              <1> ;		; will be performed for writing 4096 bytes
  4065                              <1> ;		; (2*2048, 8*512). 
  4066                              <1> ;	; ESI = Logical disk description table address
  4067                              <1> ;	; EBX = Buffer (Page) address
  4068                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4069                              <1> ;	; ECX = Sector count ; 8 sectors
  4070                              <1> ;	; edx = PTE address
  4071                              <1> ;	call	logical_disk_write
  4072                              <1> ;	; edx = PTE address
  4073                              <1> ;	pop	ecx ; sector address	
  4074                              <1> ;	jnc	short swpout_write_ok
  4075                              <1> ;	;
  4076                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4077                              <1> ;swpout_dw_err:
  4078                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4079                              <1> ;	mov	[u.error], eax
  4080                              <1> ;	jmp	short swpout_retn
  4081                              <1> ;	;
  4082                              <1> ;swpout_write_ok:
  4083                              <1> ;	; EBX = Buffer (page) address
  4084                              <1> ;	; EDX = Page Table Entry address
  4085                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4086                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4087                              <1> ;	mov 	[edx], ecx 
  4088                              <1> ;		; bit 0 = 0 (swapped page)
  4089                              <1> ;	mov	eax, ebx
  4090                              <1> ;swpout_retn:
  4091                              <1> ;	pop	ecx ; ***
  4092                              <1> ;	pop	esi ; **
  4093                              <1> ;	pop	ebx ; *
  4094                              <1> ;	retn
  4095                              <1> ;
  4096                              <1> ;;swpout_dnp_err:
  4097                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4098                              <1> ;;	jmp	short swpout_err_retn
  4099                              <1> ;swpout_nfspc_err:
  4100                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4101                              <1> ;swpout_err_retn:
  4102                              <1> ;	mov	[u.error], eax
  4103                              <1> ;	;stc
  4104                              <1> ;	retn
  4105                              <1> ;swpout_npts_err:
  4106                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4107                              <1> ;	pop	ebx
  4108                              <1> ;	jmp	short swpout_err_retn
  4109                              <1> ;swpout_im_err:
  4110                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4111                              <1> ;	jmp	short swpout_err_retn
  4112                              <1> 
  4113                              <1> ; 24/12/2021
  4114                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4115                              <1> 
  4116                              <1> ;swap_queue_shift:
  4117                              <1> 	; 26/03/2017
  4118                              <1> 	; 10/06/2016
  4119                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4120                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4121                              <1> 	;
  4122                              <1> 	; INPUT ->
  4123                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4124                              <1> 	;	      and process number combination (bit 0 to 11)
  4125                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4126                              <1> 	;	
  4127                              <1> 	; OUTPUT ->
  4128                              <1> 	;	If EBX input > 0 
  4129                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4130                              <1> 	; 	   from the tail to the head, up to entry offset
  4131                              <1> 	; 	   which points to EBX input value or nothing
  4132                              <1> 	;	   to do if EBX value is not found on the queue.
  4133                              <1> 	;	   (The entry -with EBX value- will be removed
  4134                              <1> 	;	   from the queue if it is found.)
  4135                              <1> 	;
  4136                              <1> 	;	   EAX = 0		
  4137                              <1> 	;
  4138                              <1> 	;	If EBX input = 0
  4139                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4140                              <1> 	; 	   from the tail to the head, if the PTE address
  4141                              <1> 	;	   which is pointed in head of the queue is marked
  4142                              <1> 	;	   as "accessed" or it is marked as "non present".
  4143                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4144                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4145                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4146                              <1> 	;	   -without dropping pointer of the PTE from 
  4147                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4148                              <1> 	;	   Pointer in the head will be moved into the tail,
  4149                              <1> 	;	   other PTEs will be shifted on head direction.)
  4150                              <1> 	;
  4151                              <1> 	;	   Swap queue will be shifted up to the first
  4152                              <1> 	;	   'present' or 'non accessed' page will be found
  4153                              <1> 	;	   (as pointed) on the queue head (then it will be
  4154                              <1>         ;          removed/dropped from the queue).
  4155                              <1> 	;
  4156                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4157                              <1> 	;		 (it's pointer -virtual address-) dropped
  4158                              <1> 	;		 (removed) from swap queue.
  4159                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4160                              <1> 	;	         which is (it's pointer -virtual address-)
  4161                              <1> 	;		 dropped (removed) from swap queue.
  4162                              <1> 	;
  4163                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4164                              <1> 	;
  4165                              <1> 	; Modified Registers -> EAX, EBX
  4166                              <1> 	;
  4167                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4168                              <1> ;	and	ax, ax
  4169                              <1> ;	jz	short swpqs_retn
  4170                              <1> ;	push	edi
  4171                              <1> ;	push	esi
  4172                              <1> ;	push	ecx
  4173                              <1> ;	mov	esi, swap_queue
  4174                              <1> ;	mov	ecx, eax
  4175                              <1> ;	or	ebx, ebx
  4176                              <1> ;	jz	short swpqs_7
  4177                              <1> ;swpqs_1:
  4178                              <1> ;	lodsd
  4179                              <1> ;	cmp	eax, ebx
  4180                              <1> ;	je	short swpqs_2
  4181                              <1> ;	loop	swpqs_1
  4182                              <1> ;	; 10/06/2016
  4183                              <1> ;	sub	eax, eax 
  4184                              <1> ;	jmp	short swpqs_6
  4185                              <1> ;swpqs_2:
  4186                              <1> ;	mov	edi, esi
  4187                              <1> ;	sub 	edi, 4
  4188                              <1> ;swpqs_3:
  4189                              <1> ;	dec	word [swpq_count]
  4190                              <1> ;	jz	short swpqs_5
  4191                              <1> ;swpqs_4:
  4192                              <1> ;	dec 	ecx
  4193                              <1> ;	rep	movsd	; shift up (to the head)
  4194                              <1> ;swpqs_5:
  4195                              <1> ;	xor	eax, eax
  4196                              <1> ;	mov	[edi], eax
  4197                              <1> ;swpqs_6:
  4198                              <1> ;	pop	ecx
  4199                              <1> ;	pop	esi
  4200                              <1> ;	pop	edi
  4201                              <1> ;swpqs_retn:
  4202                              <1> ;	retn		
  4203                              <1> ;swpqs_7:
  4204                              <1> ;	mov	edi, esi ; head
  4205                              <1> ;	lodsd
  4206                              <1> ;	; 20/07/2015
  4207                              <1> ;	mov	ebx, eax
  4208                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4209                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4210                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4211                              <1> ;		      ; ax = process number (1 to 4095)
  4212                              <1> ;	cmp	al, [u.uno]
  4213                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4214                              <1> ;	jne	short swpqs_8
  4215                              <1> ;	mov	eax, [u.pgdir]
  4216                              <1> ;	jmp	short swpqs_9
  4217                              <1> ;swpqs_8:
  4218                              <1> ;	; 09/06/2016
  4219                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4220                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4221                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4222                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4223                              <1> ;
  4224                              <1> ;	;shl	ax, 2
  4225                              <1> ;	shl	al, 2
  4226                              <1> ;	mov 	eax, [eax+p.upage-4]
  4227                              <1> ;	or	eax, eax
  4228                              <1> ;	jz	short swpqs_3 ; invalid upage
  4229                              <1> ;	add	eax, u.pgdir - user
  4230                              <1> ;			 ; u.pgdir value for the process
  4231                              <1> ;			 ; is in [eax]
  4232                              <1> ;	mov	eax, [eax]
  4233                              <1> ;	and	eax, eax
  4234                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4235                              <1> ;swpqs_9:
  4236                              <1> ;	push	edx
  4237                              <1> ;	; eax = page directory
  4238                              <1> ;	; ebx = virtual address
  4239                              <1> ;	call	get_pte
  4240                              <1> ;	mov	ebx, edx	; PTE address
  4241                              <1> ;	pop	edx
  4242                              <1> ;	; 10/06/2016
  4243                              <1> ;	jc	short swpqs_13 ; empty PDE
  4244                              <1> ;	; EAX = PTE value
  4245                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4246                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4247                              <1> ;			        ; from the queue (head)
  4248                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4249                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4250                              <1> ;			        ; from the queue (head) 	
  4251                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4252                              <1> ;	;jnz	short swpqs_11  ; present
  4253                              <1> ;			        ; accessed page
  4254                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4255                              <1> ;	jc	short swpqs_11  ; accessed page
  4256                              <1> ;
  4257                              <1> ;	dec	ecx
  4258                              <1> ;	mov	[swpq_count], cx
  4259                              <1> ;       jz      short swpqs_10
  4260                              <1> ;		; esi = head + 4
  4261                              <1> ;		; edi = head
  4262                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4263                              <1> ;swpqs_10:
  4264                              <1> ;	mov	[edi], ecx ; 0
  4265                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4266                              <1> ;
  4267                              <1> ;swpqs_11:
  4268                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4269                              <1> ;	; Rotation (head -> tail)
  4270                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4271                              <1> ;	jz	short swpqs_10
  4272                              <1> ;		; esi = head + 4
  4273                              <1> ;		; edi = head
  4274                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4275                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4276                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4277                              <1> ;
  4278                              <1> ;	mov	cx, [swpq_count]
  4279                              <1> ;
  4280                              <1> ;swpqs_12:
  4281                              <1> ;	mov	esi, swap_queue ; head
  4282                              <1> ;       jmp     swpqs_7
  4283                              <1> ;
  4284                              <1> ;swpqs_13:
  4285                              <1> ;	dec	ecx
  4286                              <1> ;	mov	[swpq_count], cx
  4287                              <1> ;       jz      swpqs_5
  4288                              <1> ;	jmp	short swpqs_12
  4289                              <1> 
  4290                              <1> ; 24/12/2021
  4291                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4292                              <1> 
  4293                              <1> ;add_to_swap_queue:
  4294                              <1> 	; 20/02/2017
  4295                              <1> 	; 20/07/2015
  4296                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4297                              <1> 	;
  4298                              <1> 	; Adds new page to swap queue
  4299                              <1> 	; (page directories and page tables must not be added
  4300                              <1> 	; to swap queue)	
  4301                              <1> 	;
  4302                              <1> 	; INPUT ->
  4303                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4304                              <1> 	;	[u.uno]
  4305                              <1> 	;	20/02/2017
  4306                              <1> 	;	(Linear address = CORE + user's virtual address)
  4307                              <1> 	;
  4308                              <1> 	; OUTPUT ->
  4309                              <1> 	;	EAX = [swpq_count]
  4310                              <1> 	;	      (after the PTE has been added)
  4311                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4312                              <1> 	;	      the PTE could not be added.
  4313                              <1> 	;
  4314                              <1> 	; Modified Registers -> EAX
  4315                              <1> 	;
  4316                              <1> ;	push	ebx
  4317                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4318                              <1> ;	mov	bl, [u.uno] ; current process number
  4319                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4320                              <1> ;				 ; it is already on the queue
  4321                              <1> ;		; then add it to the tail of the queue
  4322                              <1> ;	movzx	eax, word [swpq_count]
  4323                              <1> ;	cmp	ax, 1024
  4324                              <1> ;	jb	short atsq_1
  4325                              <1> ;	sub	ax, ax
  4326                              <1> ;	pop	ebx
  4327                              <1> ;	retn
  4328                              <1> ;atsq_1:
  4329                              <1> ;	push	esi
  4330                              <1> ;	mov	esi, swap_queue
  4331                              <1> ;	and	ax, ax
  4332                              <1> ;	jz	short atsq_2
  4333                              <1> ;	shl	ax, 2	; convert to offset
  4334                              <1> ;	add	esi, eax
  4335                              <1> ;	shr	ax, 2
  4336                              <1> ;atsq_2:
  4337                              <1> ;	inc	ax
  4338                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4339                              <1> ;	mov	[swpq_count], ax
  4340                              <1> ;	pop	esi
  4341                              <1> ;	pop	ebx
  4342                              <1> ;	retn
  4343                              <1> 
  4344                              <1> ; 24/12/2021
  4345                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4346                              <1> 
  4347                              <1> ;unlink_swap_block:
  4348                              <1> 	; 15/09/2015
  4349                              <1> 	; 30/04/2015
  4350                              <1> 	; 18/04/2015
  4351                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4352                              <1> 	;
  4353                              <1> 	; INPUT -> 
  4354                              <1> 	;	EAX = swap disk/file offset address
  4355                              <1> 	;	      (bit 1 to bit 31)
  4356                              <1> 	; OUTPUT ->
  4357                              <1> 	;	[swpd_free] is increased
  4358                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4359                              <1> 	;
  4360                              <1> 	; Modified Registers -> EAX
  4361                              <1> 	;
  4362                              <1> ;	push	ebx
  4363                              <1> ;	push	edx
  4364                              <1> ;	;
  4365                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4366                              <1> ;				     ; 3 bits right
  4367                              <1> ;				     ; to get swap block/page number
  4368                              <1> ;	mov	edx, eax
  4369                              <1> ;	; 15/09/2015
  4370                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4371                              <1> ;				     ; (1 allocation bit = 1 page)
  4372                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4373                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4374                              <1> ;				     ; (to get 32 bit position)			
  4375                              <1> ;	;
  4376                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4377                              <1> ;	add	ebx, edx
  4378                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4379                              <1> ;				     ; (allocation bit position)	 
  4380                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4381                              <1> ;				     ; than the address in 'swpd_next' ?
  4382                              <1> ;				     ; (next/first free block value)		
  4383                              <1> ;	jnb	short uswpbl_1	     ; no	
  4384                              <1> ;	mov	[swpd_next], eax     ; yes	
  4385                              <1> ;uswpbl_1:
  4386                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4387                              <1> ;				     ; set relevant bit to 1.
  4388                              <1> ;				     ; set CF to the previous bit value	
  4389                              <1> ;	cmc			     ; complement carry flag	
  4390                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4391                              <1> ;				     ; if the block is already deallocated
  4392                              <1> ;				     ; before.	
  4393                              <1> ;       inc     dword [swpd_free]
  4394                              <1> ;uswpbl_2:
  4395                              <1> ;	pop	edx
  4396                              <1> ;	pop	ebx
  4397                              <1> ;	retn
  4398                              <1> 
  4399                              <1> ; 24/12/2021
  4400                              <1> ; ('link_swap_block' procedure call is disabled)
  4401                              <1> 
  4402                              <1> ;link_swap_block:
  4403                              <1> 	; 01/07/2015
  4404                              <1> 	; 18/04/2015
  4405                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4406                              <1> 	;
  4407                              <1> 	; INPUT -> none
  4408                              <1> 	;
  4409                              <1> 	; OUTPUT ->
  4410                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4411                              <1> 	;	      in sectors (corresponding 
  4412                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4413                              <1> 	;
  4414                              <1> 	;	CF = 1 and EAX = 0 
  4415                              <1> 	; 		   if there is not a free block to be allocated	
  4416                              <1> 	;
  4417                              <1> 	; Modified Registers -> none (except EAX)
  4418                              <1> 	;
  4419                              <1> 
  4420                              <1> ;	;mov	eax, [swpd_free]
  4421                              <1> ;	;and	eax, eax
  4422                              <1> ;	;jz	short out_of_swpspc
  4423                              <1> ;	;
  4424                              <1> ;	push	ebx
  4425                              <1> ;	push	ecx
  4426                              <1> ;	;
  4427                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4428                              <1> ;	mov	ecx, ebx
  4429                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4430                              <1> ;				 ; next_free_swap_block >> 5
  4431                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4432                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4433                              <1> ;lswbl_scan:
  4434                              <1> ;	cmp	ebx, ecx
  4435                              <1> ;	ja	short lswbl_notfound
  4436                              <1> ;	;
  4437                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4438                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4439                              <1> ;			   ; loads the destination with an index to
  4440                              <1> ;			   ; first set bit. (0 -> 31) 
  4441                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4442                              <1> ;	; 01/07/2015
  4443                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4444                              <1> ;			 ;
  4445                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4446                              <1> ;			 ;	  with value of 1 means 
  4447                              <1> ;			 ;	  the corresponding page is free 
  4448                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4449                              <1> ;	add	ebx, 4
  4450                              <1> ;			 ; We return back for searching next page block
  4451                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4452                              <1> ;			 ;	 we always will find at least 1 free block here.
  4453                              <1> ;	jmp    	short lswbl_scan
  4454                              <1> ;	;
  4455                              <1> ;lswbl_notfound:	
  4456                              <1> ;	sub	ecx, swap_alloc_table
  4457                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4458                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4459                              <1> ;	xor	eax, eax
  4460                              <1> ;	mov	[swpd_free], eax
  4461                              <1> ;	stc
  4462                              <1> ;lswbl_ok:
  4463                              <1> ;	pop	ecx
  4464                              <1> ;	pop	ebx
  4465                              <1> ;	retn
  4466                              <1> ;	;
  4467                              <1> ;;out_of_swpspc:
  4468                              <1> ;;	stc
  4469                              <1> ;;	retn
  4470                              <1> ;
  4471                              <1> ;lswbl_found:
  4472                              <1> ;	mov	ecx, ebx
  4473                              <1> ;	sub	ecx, swap_alloc_table
  4474                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4475                              <1> ;				 ; address/offset (to the next)
  4476                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4477                              <1> ;	;
  4478                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4479                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4480                              <1> ;				 ; in the destination.
  4481                              <1> ;				 ;
  4482                              <1> ;				 ; Reset the bit which is corresponding to the 
  4483                              <1> ;				 ; (just) allocated block.
  4484                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4485                              <1> ;	add	eax, ecx	 ; = block number
  4486                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4487                              <1> ;				 ; 1 block =  8 sectors
  4488                              <1> ;	;
  4489                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4490                              <1> ;	;
  4491                              <1> ;	; NOTE: The relevant page table entry will be updated
  4492                              <1> ;	;       according to this EAX value...
  4493                              <1> ;	;
  4494                              <1> ;	jmp	short lswbl_ok
  4495                              <1> 
  4496                              <1> ; 24/12/2021
  4497                              <1> ; ('logical_disk_read' procedure call is disabled)
  4498                              <1> 
  4499                              <1> ;logical_disk_read:
  4500                              <1> 	; 20/07/2015
  4501                              <1> 	; 09/03/2015 (temporary code here)
  4502                              <1> 	;
  4503                              <1> 	; INPUT ->
  4504                              <1> 	; 	ESI = Logical disk description table address
  4505                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4506                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4507                              <1> 	; 	ECX = Sector count
  4508                              <1> 	;
  4509                              <1> 	;
  4510                              <1> ;	retn
  4511                              <1> 
  4512                              <1> ; 24/12/2021
  4513                              <1> ; ('logical_disk_write' procedure call is disabled)
  4514                              <1> 
  4515                              <1> ;logical_disk_write:
  4516                              <1> 	; 20/07/2015
  4517                              <1> 	; 09/03/2015 (temporary code here)
  4518                              <1> 	;
  4519                              <1> 	; INPUT ->
  4520                              <1> 	; 	ESI = Logical disk description table address
  4521                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4522                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4523                              <1> 	; 	ECX = Sector count
  4524                              <1> 	;
  4525                              <1> ;	retn
  4526                              <1> 
  4527                              <1> get_physical_addr:
  4528                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4529                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4530                              <1> 	; 18/10/2015
  4531                              <1> 	; 29/07/2015
  4532                              <1> 	; 20/07/2015
  4533                              <1> 	; 04/06/2015
  4534                              <1> 	; 20/05/2015
  4535                              <1> 	; 28/04/2015
  4536                              <1> 	; 18/04/2015
  4537                              <1> 	; Get physical address
  4538                              <1> 	;     (allocates a new page for user if it is not present)
  4539                              <1> 	;	
  4540                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4541                              <1> 	; (buffer) address to physical address (of the buffer).)
  4542                              <1> 	; ('sys write', 'sys read' system calls...)
  4543                              <1> 	;
  4544                              <1> 	; INPUT ->
  4545                              <1> 	;	EBX = virtual address
  4546                              <1> 	;	u.pgdir = page directory (physical) address
  4547                              <1> 	;
  4548                              <1> 	; OUTPUT ->
  4549                              <1> 	;	EAX = physical address 
  4550                              <1> 	;	EBX = linear address	
  4551                              <1> 	;	EDX = physical address of the page frame
  4552                              <1> 	;	      (with attribute bits)
  4553                              <1> 	;	ECX = byte count within the page frame
  4554                              <1> 	;
  4555                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4556                              <1> 	;
  4557                              <1> 
  4558                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4559 000031A4 A1[116F0000]        <1> 	mov	eax, [u.pgdir]
  4560                              <1> 
  4561                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4562                              <1> 	
  4563 000031A9 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4564                              <1> 	;
  4565                              <1> 	;mov	eax, [u.pgdir]
  4566 000031AF E816FDFFFF          <1> 	call	get_pte
  4567                              <1> 		; EDX = Page table entry address (if CF=0)
  4568                              <1> 	        ;       Page directory entry address (if CF=1)
  4569                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4570                              <1> 		; EAX = Page table entry value (page address)
  4571                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4572 000031B4 731C                <1> 	jnc	short gpa_1
  4573                              <1> 	;
  4574 000031B6 E8FDFBFFFF          <1> 	call	allocate_page
  4575 000031BB 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4576                              <1> gpa_0:
  4577 000031BD E867FCFFFF          <1> 	call 	clear_page
  4578                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4579 000031C2 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4580                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4581                              <1> 			   ; (user, writable, present page)	
  4582 000031C4 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4583 000031C6 A1[116F0000]        <1> 	mov	eax, [u.pgdir]	
  4584 000031CB E8FAFCFFFF          <1> 	call	get_pte
  4585 000031D0 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4586                              <1> gpa_1:
  4587                              <1> 	; EAX = PTE value, EDX = PTE address
  4588 000031D2 A801                <1> 	test 	al, PTE_A_PRESENT
  4589 000031D4 750A                <1> 	jnz	short gpa_3
  4590 000031D6 09C0                <1> 	or	eax, eax
  4591 000031D8 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4592                              <1> 
  4593                              <1> ; 24/12/2021
  4594                              <1> ; ('reload_page' procedure call is disabled)
  4595 000031DA EB2C                <1> 	jmp	short gpa_im_err
  4596                              <1> 
  4597                              <1> 	; 20/07/2015
  4598                              <1> ;	push	ebp
  4599                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4600                              <1> ;	; reload swapped page
  4601                              <1> ;	call	reload_page ; 28/04/2015
  4602                              <1> ;	pop	ebp
  4603                              <1> ;	jc	short gpa_retn
  4604                              <1> gpa_2:
  4605                              <1> ; 24/12/2021
  4606                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4607                              <1> 
  4608                              <1> 	; 20/07/2015
  4609                              <1> 	; 20/05/2015
  4610                              <1> 	; add this page to swap queue
  4611                              <1> ;	push	eax 
  4612                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4613                              <1> ;	call 	add_to_swap_queue
  4614                              <1> ;	pop	eax
  4615                              <1> 		; PTE address in EDX
  4616                              <1> 		; virtual address in EBX
  4617                              <1> 	; EAX = memory page address
  4618 000031DC 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4619                              <1> 				  ; present flag, bit 0 = 1
  4620                              <1> 				  ; user flag, bit 2 = 1	
  4621                              <1> 				  ; writable flag, bit 1 = 1
  4622 000031DE 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4623                              <1> gpa_3:
  4624                              <1> 	; 18/10/2015
  4625 000031E0 89D9                <1> 	mov	ecx, ebx
  4626 000031E2 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4627 000031E8 89C2                <1> 	mov 	edx, eax
  4628 000031EA 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4629 000031EE 01C8                <1> 	add	eax, ecx
  4630 000031F0 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4631 000031F2 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4632 000031F8 F8                  <1> 	clc
  4633                              <1> gpa_retn:
  4634 000031F9 C3                  <1> 	retn	
  4635                              <1> gpa_4:	
  4636 000031FA E8B9FBFFFF          <1> 	call	allocate_page
  4637 000031FF 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4638 00003201 E823FCFFFF          <1> 	call	clear_page
  4639 00003206 EBD4                <1> 	jmp	short gpa_2
  4640                              <1> 
  4641                              <1> gpa_im_err:	
  4642 00003208 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4643                              <1> 				  ; Major error = 0 (No protection fault)	
  4644 0000320D C3                  <1> 	retn
  4645                              <1> 
  4646                              <1> ; 24/12/2021
  4647                              <1> ; ('reload_page' procedure call is disabled)
  4648                              <1> 
  4649                              <1> ;reload_page:
  4650                              <1> 	; 20/07/2015
  4651                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4652                              <1> 	;
  4653                              <1> 	; Reload (Restore) swapped page at memory
  4654                              <1> 	;
  4655                              <1> 	; INPUT -> 
  4656                              <1> 	;	EBP = Virtual (linear) memory address
  4657                              <1> 	;	EAX = PTE value (swap disk sector address)
  4658                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4659                              <1> 	; OUTPUT ->
  4660                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4661                              <1> 	;
  4662                              <1> 	;	CF = 1 and EAX = error code
  4663                              <1> 	;
  4664                              <1> 	; Modified Registers -> none (except EAX)
  4665                              <1> 	;
  4666                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4667                              <1> ;	push	ebx      ;
  4668                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4669                              <1> ;	call	allocate_page
  4670                              <1> ;	jc	short rlp_im_err
  4671                              <1> ;	xchg 	eax, ebx	
  4672                              <1> ;	; EBX = Physical memory (page) address
  4673                              <1> ;	; EAX = Swap disk (offset) address
  4674                              <1> ;	; EBP = Virtual (linear) memory address
  4675                              <1> ;	call	swap_in
  4676                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4677                              <1> ;	mov	eax, ebx	
  4678                              <1> ;rlp_retn:
  4679                              <1> ;	pop	ebx
  4680                              <1> ;	retn
  4681                              <1> ;	
  4682                              <1> ;rlp_im_err:	
  4683                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4684                              <1> ;				  ; Major error = 0 (No protection fault)	
  4685                              <1> ;	jmp	short rlp_retn
  4686                              <1> ;
  4687                              <1> ;rlp_swp_err:
  4688                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4689                              <1> ;	jmp	short rlp_retn
  4690                              <1> 
  4691                              <1> copy_page_dir:
  4692                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4693                              <1> 	; 19/09/2015
  4694                              <1> 	; temporary - 07/09/2015
  4695                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4696                              <1> 	;
  4697                              <1> 	; INPUT -> 
  4698                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4699                              <1> 	;		    page directory.
  4700                              <1> 	; OUTPUT ->
  4701                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4702                              <1> 	;	       page directory.
  4703                              <1> 	;	(New page directory with new page table entries.)
  4704                              <1> 	;	(New page tables with read only copies of the parent's
  4705                              <1> 	;	pages.)
  4706                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4707                              <1> 	;
  4708                              <1> 	; Modified Registers -> none (except EAX)
  4709                              <1> 	;
  4710 0000320E E8A5FBFFFF          <1> 	call	allocate_page
  4711 00003213 723E                <1> 	jc	short cpd_err
  4712                              <1> 	;
  4713 00003215 55                  <1> 	push	ebp ; 20/07/2015
  4714 00003216 56                  <1> 	push	esi
  4715 00003217 57                  <1> 	push	edi
  4716 00003218 53                  <1> 	push	ebx
  4717 00003219 51                  <1> 	push	ecx
  4718 0000321A 8B35[116F0000]      <1> 	mov	esi, [u.pgdir]
  4719 00003220 89C7                <1> 	mov	edi, eax
  4720 00003222 50                  <1> 	push	eax ; save child's page directory address
  4721                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4722                              <1> 	; (use same system space for all user page tables) 
  4723 00003223 A5                  <1> 	movsd
  4724 00003224 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4725 00003229 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4726                              <1> cpd_0:	
  4727 0000322E AD                  <1> 	lodsd
  4728                              <1> 	;or	eax, eax
  4729                              <1>         ;jnz	short cpd_1
  4730 0000322F A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4731 00003231 7508                <1> 	jnz	short cpd_1
  4732                              <1>  	; (virtual address at the end of the page table)	
  4733 00003233 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4734 00003239 EB0F                <1> 	jmp	short cpd_2
  4735                              <1> cpd_1:	
  4736 0000323B 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4737 0000323F 89C3                <1> 	mov	ebx, eax
  4738                              <1> 	; EBX = Parent's page table address
  4739 00003241 E81F000000          <1> 	call	copy_page_table
  4740 00003246 720C                <1> 	jc	short cpd_p_err
  4741                              <1> 	; EAX = Child's page table address
  4742 00003248 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4743                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4744                              <1> 			 ; (present, writable, user)
  4745                              <1> cpd_2:
  4746 0000324A AB                  <1> 	stosd
  4747 0000324B E2E1                <1> 	loop	cpd_0
  4748                              <1> 	;
  4749 0000324D 58                  <1> 	pop	eax  ; restore child's page directory address
  4750                              <1> cpd_3:
  4751 0000324E 59                  <1> 	pop	ecx
  4752 0000324F 5B                  <1> 	pop	ebx
  4753 00003250 5F                  <1> 	pop	edi
  4754 00003251 5E                  <1> 	pop	esi
  4755 00003252 5D                  <1> 	pop	ebp
  4756                              <1> cpd_err:
  4757 00003253 C3                  <1> 	retn
  4758                              <1> cpd_p_err:
  4759                              <1> 	; release the allocated pages missing (recover free space)
  4760 00003254 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4761 00003255 8B1D[116F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4762 0000325B E888FCFFFF          <1> 	call 	deallocate_page_dir
  4763 00003260 29C0                <1> 	sub	eax, eax ; 0
  4764 00003262 F9                  <1> 	stc
  4765 00003263 EBE9                <1> 	jmp	short cpd_3	
  4766                              <1> 
  4767                              <1> copy_page_table:
  4768                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4769                              <1> 	; 19/09/2015
  4770                              <1> 	; temporary - 07/09/2015
  4771                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4772                              <1> 	;
  4773                              <1> 	; INPUT -> 
  4774                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4775                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4776                              <1> 	; OUTPUT ->
  4777                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4778                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4779                              <1> 	;	CF = 1 -> error 
  4780                              <1> 	;
  4781                              <1> 	; Modified Registers -> EBP (except EAX)
  4782                              <1> 	;
  4783 00003265 E84EFBFFFF          <1> 	call	allocate_page
  4784 0000326A 7244                <1> 	jc	short cpt_err
  4785                              <1> 	;
  4786 0000326C 50                  <1> 	push	eax ; *
  4787                              <1> 	;push 	ebx
  4788 0000326D 56                  <1> 	push	esi
  4789 0000326E 57                  <1> 	push	edi
  4790 0000326F 52                  <1> 	push	edx
  4791 00003270 51                  <1> 	push	ecx
  4792                              <1> 	;
  4793 00003271 89DE                <1> 	mov	esi, ebx
  4794 00003273 89C7                <1> 	mov	edi, eax
  4795 00003275 89C2                <1> 	mov	edx, eax
  4796 00003277 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4797                              <1> cpt_0:
  4798 0000327D AD                  <1> 	lodsd
  4799 0000327E A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4800                              <1> 	;jnz	short cpt_1 (*)
  4801                              <1> 	; 24/12/2021
  4802                              <1> 	;and	eax, eax (*)
  4803 00003280 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4804                              <1> 	
  4805                              <1> ; 24/12/2021
  4806                              <1> ; ('reload_page' procedure call is disabled)
  4807                              <1> ;
  4808                              <1> ;	; ebp = virtual (linear) address of the memory page
  4809                              <1> ;	call	reload_page ; 28/04/2015
  4810                              <1> ;	jc	short cpt_p_err
  4811                              <1> cpt_1:
  4812 00003282 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4813 00003286 89C1                <1> 	mov	ecx, eax
  4814                              <1> 	; Allocate a new page for the child process
  4815 00003288 E82BFBFFFF          <1> 	call	allocate_page
  4816 0000328D 721C                <1> 	jc	short cpt_p_err
  4817 0000328F 57                  <1> 	push	edi
  4818 00003290 56                  <1> 	push	esi
  4819 00003291 89CE                <1> 	mov	esi, ecx
  4820 00003293 89C7                <1> 	mov	edi, eax
  4821 00003295 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4822 0000329A F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4823 0000329C 5E                  <1> 	pop	esi
  4824 0000329D 5F                  <1> 	pop	edi
  4825                              <1> 	; 
  4826                              <1> ; 24/12/2021
  4827                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4828                              <1> ;
  4829                              <1> ;	push	ebx
  4830                              <1> ;	push	eax
  4831                              <1> ;	mov	ebx, ebp
  4832                              <1> ;	; ebx = virtual address of the memory page
  4833                              <1> ;	call	add_to_swap_queue
  4834                              <1> ;	pop	eax
  4835                              <1> ;	pop	ebx
  4836                              <1> 	;
  4837                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4838 0000329E 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4839                              <1> cpt_2:
  4840 000032A0 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4841                              <1> 	;
  4842 000032A1 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4843                              <1> 	;
  4844 000032A7 39D7                <1> 	cmp	edi, edx
  4845 000032A9 72D2                <1> 	jb	short cpt_0
  4846                              <1> cpt_p_err:
  4847 000032AB 59                  <1> 	pop	ecx
  4848 000032AC 5A                  <1> 	pop	edx
  4849 000032AD 5F                  <1> 	pop	edi
  4850 000032AE 5E                  <1> 	pop	esi
  4851                              <1> 	;pop	ebx
  4852 000032AF 58                  <1> 	pop	eax ; *
  4853                              <1> cpt_err:
  4854 000032B0 C3                  <1> 	retn
  4855                              <1> 
  4856                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4857                              <1> 
  4858                              <1> ;; Data:
  4859                              <1> 
  4860                              <1> ; 09/03/2015
  4861                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4862                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4863                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4864                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4865                              <1> ;swpd_next:  dd 0 ; next free page block
  4866                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2086                                  %include 'sysdefs.inc' ; 09/03/2015
  2087                              <1> ; Retro UNIX 386 v1.1 Kernel - SYSDEFS.INC
  2088                              <1> ; Last Modification: 08/02//2022
  2089                              <1> ;
  2090                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2091                              <1> ; (Modified from 
  2092                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2093                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2094                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2095                              <1> ; ----------------------------------------------------------------------------
  2096                              <1> ;
  2097                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2098                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2099                              <1> ; <Bell Laboratories (17/3/1972)>
  2100                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2101                              <1> ;
  2102                              <1> ; ****************************************************************************
  2103                              <1> 
  2104                              <1> nproc 	equ	16  ; number of processes
  2105                              <1> nfiles 	equ	50
  2106                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2107                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2108                              <1> 
  2109                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2110                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2111                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2112                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2113                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2114                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2115                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2116                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2117                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2118                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2119                              <1> 	; '/core' dump file size = 32768 bytes
  2120                              <1>  
  2121                              <1> ; 08/03/2014 
  2122                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2123                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2124                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2125                              <1> 
  2126                              <1> ; 30/08/2013
  2127                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2128                              <1> 
  2129                              <1> ; 05/02/2014
  2130                              <1> ; process status
  2131                              <1> ;SFREE 	equ 0
  2132                              <1> ;SRUN	equ 1
  2133                              <1> ;SWAIT	equ 2
  2134                              <1> ;SZOMB	equ 3
  2135                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2136                              <1> 
  2137                              <1> ; 09/03/2015
  2138                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2139                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2140                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2141                              <1> 
  2142                              <1> ; 17/09/2015
  2143                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2144                              <1> 
  2145                              <1> ; 21/09/2015 (36) 
  2146                              <1> ; 01/07/2015 (35)
  2147                              <1> ; 14/07/2013 (0-34)
  2148                              <1> ; UNIX v1 system calls
  2149                              <1> _rele 	equ 0
  2150                              <1> _exit 	equ 1
  2151                              <1> _fork 	equ 2
  2152                              <1> _read 	equ 3
  2153                              <1> _write	equ 4
  2154                              <1> _open	equ 5
  2155                              <1> _close 	equ 6
  2156                              <1> _wait 	equ 7
  2157                              <1> _creat 	equ 8
  2158                              <1> _link 	equ 9
  2159                              <1> _unlink	equ 10
  2160                              <1> _exec	equ 11
  2161                              <1> _chdir	equ 12
  2162                              <1> _time 	equ 13
  2163                              <1> _mkdir 	equ 14
  2164                              <1> _chmod	equ 15
  2165                              <1> _chown	equ 16
  2166                              <1> _break	equ 17
  2167                              <1> _stat	equ 18
  2168                              <1> _seek	equ 19
  2169                              <1> _tell 	equ 20
  2170                              <1> _mount	equ 21
  2171                              <1> _umount	equ 22
  2172                              <1> _setuid	equ 23
  2173                              <1> _getuid	equ 24
  2174                              <1> _stime	equ 25
  2175                              <1> _quit	equ 26	
  2176                              <1> _intr	equ 27
  2177                              <1> _fstat	equ 28
  2178                              <1> _emt 	equ 29
  2179                              <1> _mdate 	equ 30
  2180                              <1> _stty 	equ 31
  2181                              <1> _gtty	equ 32
  2182                              <1> _ilgins	equ 33
  2183                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2184                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2185                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2186                              <1> 
  2187                              <1> %macro sys 1-4
  2188                              <1>     ; 13/04/2015
  2189                              <1>     ; Retro UNIX 386 v1 system call.		
  2190                              <1>     mov eax, %1
  2191                              <1>     %if %0 >= 2   
  2192                              <1>         mov ebx, %2
  2193                              <1>         %if %0 >= 3    
  2194                              <1>             mov ecx, %3
  2195                              <1>             %if %0 = 4
  2196                              <1>                mov edx, %4   
  2197                              <1>             %endif
  2198                              <1>         %endif
  2199                              <1>     %endif
  2200                              <1>     int 30h	   
  2201                              <1> %endmacro
  2202                              <1> 
  2203                              <1> ; 13/05/2015 - ERROR CODES
  2204                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2205                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2206                              <1> ; 14/05/2015
  2207                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2208                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2209                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2210                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2211                              <1> ; 16/05/2015		
  2212                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2213                              <1> ; 18/05/2015
  2214                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2215                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2216                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2217                              <1> ; 07/06/2015
  2218                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2219                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2220                              <1> ; 09/06/2015
  2221                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2222                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2223                              <1> ; 16/06/2015
  2224                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2225                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2226                              <1> ; 22/06/2015
  2227                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2228                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2229                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2230                              <1> ; 23/06/2015
  2231                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2232                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2233                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2234                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2235                              <1> ; 27/06/2015
  2236                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2237                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2238                              <1> ; 29/06/2015
  2239                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2240                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2241                              <1> ; 08/02/2022 
  2242                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2243                              <1> ; 10/10/2016
  2244                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2245                              <1> ; 18/05/2016
  2246                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2247                              <1> ; 15/10/2016
  2248                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2249                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2250                              <1> ; 16/10/2016
  2251                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2252                              <1> ; 08/02/2022
  2253                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2254                              <1> 
  2255                              <1> ; 26/08/2015
  2256                              <1> ; 24/07/2015
  2257                              <1> ; 24/06/2015
  2258                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2259                              <1> ; 01/07/2015
  2260                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2261                              <1> ; 24/12/2021
  2262                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  2087                                  %include 'u0.s'        ; 15/03/2015
  2088                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS0.INC
  2089                              <1> ; Last Modification: 26/02/2022
  2090                              <1> ; ----------------------------------------------------------------------------
  2091                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2092                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2093                              <1> ;
  2094                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2095                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2096                              <1> ; <Bell Laboratories (17/3/1972)>
  2097                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2098                              <1> ;
  2099                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2100                              <1> ;
  2101                              <1> ; ****************************************************************************
  2102                              <1> 
  2103                              <1> sys_init:
  2104                              <1> 	; 26/02/2022
  2105                              <1> 	; 08/01/2022
  2106                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2107                              <1> 	; 18/10/2015
  2108                              <1> 	; 28/08/2015
  2109                              <1> 	; 24/08/2015
  2110                              <1> 	; 14/08/2015
  2111                              <1> 	; 24/07/2015 
  2112                              <1> 	; 02/07/2015
  2113                              <1> 	; 01/07/2015
  2114                              <1> 	; 23/06/2015
  2115                              <1> 	; 15/04/2015
  2116                              <1> 	; 13/03/2015
  2117                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2118                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2119                              <1> 	;
  2120                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2121                              <1> 	;
  2122                              <1> 	; 14/02/2014
  2123                              <1> 	; 14/07/2013
  2124                              <1> 	;;mov	ax, 41
  2125                              <1> 	; 24/12/2021
  2126                              <1> 	;xor	eax, eax
  2127                              <1> 	;mov	al, 41
  2128                              <1> 	;mov	[rootdir], ax
  2129                              <1> 	;mov	[u.cdir], ax
  2130                              <1> 	;;and	al, 1 ; 15/04/2015
  2131                              <1> 	;inc	al  ; ax = 1
  2132 000032B1 B001                <1> 	mov	al, 1
  2133 000032B3 A2[076F0000]        <1> 	mov	[u.uno], al
  2134                              <1> 	;mov	[mpid], ax
  2135                              <1> 	;mov	[p.pid], ax
  2136 000032B8 A2[A66E0000]        <1> 	mov	[mpid], al
  2137 000032BD A2[D86B0000]        <1> 	mov	[p.pid], al	
  2138 000032C2 A2[386C0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2139                              <1> 	; 24/12/2021
  2140 000032C7 B029                <1> 	mov	al, 41
  2141                              <1> 	;mov	[rootdir], ax
  2142                              <1> 	;mov	[u.cdir], ax
  2143 000032C9 A2[A86E0000]        <1> 	mov	[rootdir], al
  2144 000032CE A2[BC6E0000]        <1> 	mov	[u.cdir], al
  2145                              <1> 	;
  2146 000032D3 B004                <1> 	mov	al, time_count ; 30/08/2013
  2147 000032D5 A2[FA6E0000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2148                              <1> 	; 02/07/2015
  2149 000032DA A1[F86A0000]        <1> 	mov	eax, [k_page_dir]
  2150                              <1> 	;sub	eax, eax
  2151 000032DF A3[116F0000]        <1> 	mov	[u.pgdir], eax ; reset
  2152                              <1> 	; 18/10/2015
  2153                              <1> 	;mov	[u.ppgdir], eax ; 0
  2154                              <1> 	; 26/02/2022
  2155                              <1>  	;call	epoch
  2156                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2157                              <1> 	; 17/07/2013
  2158 000032E4 E88F060000          <1> 	call 	bf_init ; buffer initialization
  2159                              <1> 	; 26/02/2022
  2160                              <1> 	; (save sysinit time on sb0)
  2161 000032E9 E829030000          <1> 	call	epoch
  2162 000032EE A3[047D0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2163                              <1> 	; 23/06/2015
  2164 000032F3 E8C0FAFFFF          <1> 	call	allocate_page
  2165                              <1> 	;;jc	error
  2166                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2167                              <1> 	; 24/12/2021
  2168 000032F8 7305                <1> 	jnc	short sysinit_1
  2169 000032FA E989000000          <1> 	jmp	panic
  2170                              <1> sysinit_1:
  2171 000032FF A3[086F0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2172 00003304 A3[486C0000]        <1> 	mov	[p.upage], eax
  2173                              <1> 	;
  2174 00003309 E81BFBFFFF          <1> 	call	clear_page
  2175                              <1> 	;
  2176                              <1> 	; 14/08/2015
  2177 0000330E FA                  <1> 	cli
  2178                              <1> 	; 14/03/2015
  2179                              <1> 	; 17/01/2014
  2180 0000330F E8D0010000          <1> 	call	sp_init ; serial port initialization
  2181                              <1> 	; 14/08/2015
  2182 00003314 FB                  <1> 	sti
  2183                              <1> 	;
  2184                              <1> 	; 30/06/2015
  2185                              <1> 	;mov	esi, kernel_init_ok_msg
  2186                              <1> 	;call 	print_msg
  2187                              <1> 	;
  2188 00003315 30DB                <1> 	xor	bl, bl ; video page 0
  2189                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2190 00003317 E8042E0000          <1> 	call 	vp_clr  ; 17/07/2013
  2191 0000331C FEC3                <1> 	inc	bl
  2192 0000331E 80FB08              <1> 	cmp	bl, 8
  2193 00003321 72F4                <1> 	jb	short vp_clr_nxt
  2194                              <1> 	;
  2195                              <1> 	; 24/07/2015
  2196                              <1> 	;push    KDATA
  2197                              <1>         ;push    esp
  2198                              <1> 	;mov	[tss.esp0], esp
  2199                              <1>         ;mov     word [tss.ss0], KDATA
  2200                              <1> 	;
  2201                              <1> 	; 08/01/2022
  2202                              <1> 	; 24/08/2015
  2203                              <1> 	;; temporary (01/07/2015)
  2204                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2205                              <1> 			       ; it is not needed here !
  2206                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2207 00003323 FE0D[AF6E0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2208                              <1> 			      ; 0 = executing a system call
  2209                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2210                              <1> 	;
  2211                              <1> 	;;; 06/08/2015
  2212                              <1> 	;;;call	getch ; wait for a key stroke
  2213                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2214                              <1> ;;sys_init_msg_wait:
  2215                              <1> ;;	push 	ecx
  2216                              <1> ;;	mov	al, 1
  2217                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2218                              <1> ;;	call	getc_n
  2219                              <1> ;;	pop	ecx
  2220                              <1> ;;	jnz	short sys_init_msg_ok
  2221                              <1> ;;	loop	sys_init_msg_wait
  2222                              <1> 	;
  2223                              <1> ;;sys_init_msg_ok:
  2224                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2225 00003329 6A10                <1> 	push	KDATA ; ss
  2226 0000332B 54                  <1> 	push	esp
  2227 0000332C 9C                  <1> 	pushfd
  2228 0000332D 6A08                <1> 	push	KCODE ; cs
  2229 0000332F 68[5C330000]        <1> 	push	init_exec ; eip
  2230 00003334 8925[B06E0000]      <1> 	mov	[u.sp], esp
  2231 0000333A 1E                  <1> 	push	ds
  2232 0000333B 06                  <1> 	push	es
  2233 0000333C 0FA0                <1> 	push	fs
  2234 0000333E 0FA8                <1> 	push	gs	
  2235 00003340 60                  <1> 	pushad
  2236 00003341 8925[B46E0000]      <1> 	mov	[u.usp], esp
  2237 00003347 E8641B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2238                              <1> 		      ; and interrupt return components (for IRET)
  2239 0000334C 61                  <1> 	popad
  2240 0000334D 6658                <1> 	pop	ax ; gs
  2241 0000334F 6658                <1> 	pop	ax ; fs
  2242 00003351 6658                <1> 	pop	ax ; es
  2243 00003353 6658                <1> 	pop	ax ; ds	
  2244 00003355 58                  <1> 	pop	eax ; eip (init_exec)
  2245 00003356 6658                <1> 	pop	ax ; cs (KCODE)
  2246 00003358 58                  <1> 	pop	eax ; E-FLAGS
  2247 00003359 58                  <1> 	pop	eax ; esp
  2248 0000335A 6658                <1> 	pop	ax ; ss (KDATA)
  2249                              <1> 	;
  2250                              <1> 	; 08/01/2022 ([u.ppgdir] is zero already)
  2251                              <1> 	;xor	eax, eax ; 0
  2252                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2253                              <1> 	;
  2254                              <1> 	; 02/07/2015
  2255                              <1> 	; [u.pgdir ] = [k_page_dir]
  2256                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2257                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2258                              <1> init_exec:
  2259                              <1> 	; 13/03/2013
  2260                              <1> 	; 24/07/2013
  2261 0000335C BB[7E330000]        <1> 	mov	ebx, init_file
  2262 00003361 B9[76330000]        <1> 	mov	ecx, init_argp
  2263                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2264                              <1> 	; ECX contains address of argument list pointer
  2265                              <1> 	;
  2266                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2267                              <1> 			      ; 0 = executing a system call
  2268                              <1> 	sys	_exec  ; execute file
  2188                              <2> 
  2189                              <2> 
  2190 00003366 B80B000000          <2>  mov eax, %1
  2191                              <2>  %if %0 >= 2
  2192                              <2>  mov ebx, %2
  2193                              <2>  %if %0 >= 3
  2194                              <2>  mov ecx, %3
  2195                              <2>  %if %0 = 4
  2196                              <2>  mov edx, %4
  2197                              <2>  %endif
  2198                              <2>  %endif
  2199                              <2>  %endif
  2200 0000336B CD30                <2>  int 30h
  2269 0000336D 7319                <1> 	jnc	short panic
  2270                              <1> 	;
  2271 0000336F BE[0C680000]        <1> 	mov	esi, etc_init_err_msg
  2272                              <1> 	; 08/01/2022
  2273                              <1> 	;call 	print_msg
  2274 00003374 EB17                <1> 	jmp	short key_to_reboot
  2275                              <1> 
  2276                              <1> ;align 4
  2277                              <1> init_argp:
  2278 00003376 [7E330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2279                              <1> init_file:
  2280                              <1> 	; 24/08/2015
  2281 0000337E 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2281 00003387 00                  <1>
  2282                              <1> panic:
  2283                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2284                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2285 00003388 BE[F1670000]        <1> 	mov 	esi, panic_msg
  2286                              <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1)
  2287 0000338D E819000000          <1> 	call 	print_msg
  2288                              <1> ;key_to_reboot:
  2289                              <1> 	; 15/11/2015
  2290 00003392 E8D72B0000          <1> 	call 	getch 
  2291                              <1> 		; wait for a character from the current tty
  2292                              <1> 	;
  2293 00003397 B00A                <1> 	mov	al, 0Ah
  2294 00003399 8A1D[266B0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2295 0000339F B407                <1> 	mov	ah, 07h ; Black background, 
  2296                              <1> 			; light gray forecolor
  2297 000033A1 E821E0FFFF          <1> 	call 	write_tty
  2298 000033A6 E9BCDCFFFF          <1> 	jmp	cpu_reset 
  2299                              <1> 
  2300                              <1> print_msg:
  2301                              <1> 	; 01/07/2015
  2302                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2303                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2304                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2305                              <1> 	;
  2306                              <1> 	;
  2307 000033AB AC                  <1> 	lodsb
  2308                              <1> pmsg1:
  2309 000033AC 56                  <1> 	push 	esi
  2310 000033AD 0FB61D[266B0000]    <1> 	movzx	ebx, byte [ptty]
  2311 000033B4 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2312 000033B6 E80CE0FFFF          <1> 	call 	write_tty
  2313 000033BB 5E                  <1> 	pop	esi
  2314 000033BC AC                  <1> 	lodsb
  2315 000033BD 20C0                <1> 	and 	al, al
  2316 000033BF 75EB                <1> 	jnz 	short pmsg1
  2317 000033C1 C3                  <1> 	retn
  2318                              <1> 	
  2319                              <1> ctrlbrk:
  2320                              <1> 	; 04/02/2022
  2321                              <1> 	; 01/02/2022
  2322                              <1> 	; 12/11/2015
  2323                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2324                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2325                              <1> 	;
  2326                              <1> 	; INT 1Bh (control+break) handler
  2327                              <1> 	;
  2328                              <1>       	; Retro Unix 8086 v1 feature only!
  2329                              <1>       	;
  2330 000033C2 66833D[FC6E0000]00  <1> 	cmp 	word [u.intr], 0
  2331 000033CA 764B                <1> 	jna 	short cbrk4
  2332                              <1> cbrk0:
  2333                              <1> 	; 12/11/2015
  2334                              <1> 	; 06/12/2013
  2335 000033CC 66833D[FE6E0000]00  <1> 	cmp 	word [u.quit], 0
  2336 000033D4 7441                <1> 	jz	short cbrk4
  2337                              <1> 	;
  2338                              <1> 	; 20/09/2013	
  2339                              <1> 	;push 	ax
  2340                              <1> 	; 01/02/2022
  2341 000033D6 50                  <1> 	push	eax
  2342                              <1> 
  2343                              <1> 	; 04/02/2022
  2344                              <1> 	; (repetitive ctrl+brk check) 
  2345 000033D7 66A1[FE6E0000]      <1> 	mov	ax, [u.quit]
  2346 000033DD 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2347 000033DF 7435                <1> 	jz	short cbrk3
  2348                              <1> 
  2349                              <1> 	; 20/09/2013
  2350 000033E1 A0[266B0000]        <1> 	mov	al, [ptty]
  2351                              <1> 	;
  2352                              <1> 	; 12/11/2015
  2353                              <1> 	;
  2354                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2355                              <1> 	; or ctrl+break from console (pseudo) tty
  2356                              <1> 	; (!redirection!)
  2357                              <1> 	;
  2358 000033E6 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2359 000033E8 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2360                              <1> 	;	
  2361                              <1> 	; Serial port interrupt handler sets [ptty]
  2362                              <1> 	; to the port's tty number (as temporary).
  2363                              <1> 	;
  2364                              <1> 	; If active process is using a stdin or 
  2365                              <1> 	; stdout redirection (by the shell),
  2366                              <1>         ; console tty keyboard must be available
  2367                              <1> 	; to terminate running process,
  2368                              <1> 	; in order to prevent a deadlock. 
  2369                              <1> 	;
  2370 000033EA 52                  <1> 	push	edx
  2371 000033EB 0FB615[076F0000]    <1> 	movzx	edx, byte [u.uno]
  2372 000033F2 3A82[176C0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2373 000033F8 5A                  <1> 	pop	edx
  2374 000033F9 7412                <1> 	je	short cbrk2
  2375                              <1> cbrk1:
  2376 000033FB FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2377                              <1> 	; 06/12/2013
  2378 000033FD 3A05[E86E0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2379 00003403 7408                <1> 	je	short cbrk2	
  2380 00003405 3A05[E96E0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2381 0000340B 7509                <1> 	jne	short cbrk3	
  2382                              <1> cbrk2:
  2383                              <1> 	;; 06/12/2013
  2384                              <1> 	;mov	ax, [u.quit]
  2385                              <1> 	;and	ax, ax
  2386                              <1> 	;jz	short cbrk3
  2387                              <1> 	;
  2388                              <1> 	;xor	ax, ax ; 0
  2389                              <1> 	;dec	ax
  2390                              <1> 	; 01/02/2022
  2391 0000340D 31C0                <1> 	xor	eax, eax ; 0
  2392 0000340F 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2393                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2394 00003410 66A3[FE6E0000]      <1> 	mov	[u.quit], ax
  2395                              <1> cbrk3:
  2396                              <1> 	;pop	ax
  2397                              <1> 	; 01/02/2022
  2398 00003416 58                  <1> 	pop	eax
  2399                              <1> cbrk4:
  2400 00003417 C3                  <1> 	retn
  2401                              <1> 
  2402                              <1> com2_int:
  2403                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2404                              <1> 	; 07/11/2015 
  2405                              <1> 	; 24/10/2015
  2406                              <1> 	; 23/10/2015
  2407                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2408                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2409                              <1> 	; < serial port 2 interrupt handler >
  2410                              <1> 	;
  2411 00003418 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2412                              <1> 	;;push	eax
  2413                              <1> 	; 08/01/2022
  2414 0000341B 29C0                <1> 	sub	eax, eax
  2415 0000341D B009                <1> 	mov	al, 9
  2416                              <1> 	;mov	ax, 9
  2417 0000341F EB07                <1> 	jmp	short comm_int
  2418                              <1> com1_int:
  2419                              <1> 	; 07/11/2015
  2420                              <1> 	; 24/10/2015
  2421 00003421 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2422                              <1> 	; 23/10/2015
  2423                              <1> 	;push	eax
  2424                              <1> 	; 08/01/2022
  2425 00003424 29C0                <1> 	sub	eax, eax
  2426 00003426 B008                <1> 	mov	al, 8
  2427                              <1> 	;mov	ax, 8
  2428                              <1> comm_int:
  2429                              <1> 	; 08/01/2022
  2430                              <1> 	; 20/11/2015
  2431                              <1> 	; 18/11/2015
  2432                              <1> 	; 17/11/2015
  2433                              <1> 	; 16/11/2015
  2434                              <1> 	; 09/11/2015
  2435                              <1> 	; 08/11/2015
  2436                              <1> 	; 07/11/2015
  2437                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2438                              <1> 	; 01/11/2015
  2439                              <1> 	; 26/10/2015
  2440                              <1> 	; 23/10/2015
  2441 00003428 53                  <1> 	push	ebx
  2442 00003429 56                  <1> 	push	esi
  2443 0000342A 57                  <1> 	push	edi
  2444 0000342B 1E                  <1> 	push 	ds
  2445 0000342C 06                  <1> 	push 	es
  2446                              <1> 	; 18/11/2015
  2447 0000342D 0F20DB              <1> 	mov	ebx, cr3
  2448 00003430 53                  <1> 	push	ebx ; ****
  2449                              <1> 	;
  2450 00003431 51                  <1> 	push	ecx ; ***
  2451 00003432 52                  <1> 	push	edx ; **
  2452                              <1> 	;
  2453 00003433 BB10000000          <1> 	mov	ebx, KDATA
  2454 00003438 8EDB                <1> 	mov	ds, bx
  2455 0000343A 8EC3                <1> 	mov	es, bx
  2456                              <1> 	;
  2457 0000343C 8B0D[F86A0000]      <1> 	mov	ecx, [k_page_dir]
  2458 00003442 0F22D9              <1> 	mov	cr3, ecx
  2459                              <1> 	; 20/11/2015
  2460                              <1> 	; Interrupt identification register
  2461 00003445 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2462                              <1> 	;
  2463 00003449 3C08                <1> 	cmp 	al, 8 
  2464 0000344B 7702                <1> 	ja 	short com_i0
  2465                              <1> 	;
  2466                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2467                              <1> 	; 20/11/2015
  2468                              <1> 	; 17/11/2015
  2469                              <1> 	; 16/11/2015
  2470                              <1> 	; 15/11/2015
  2471                              <1> 	; 24/10/2015
  2472                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2473                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2474                              <1> 	; < serial port 1 interrupt handler >
  2475                              <1> 	;
  2476 0000344D FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2477                              <1> com_i0:
  2478                              <1> 	;push	eax ; *
  2479                              <1> 	; 07/11/2015
  2480 0000344F A2[666B0000]        <1> 	mov 	byte [ccomport], al
  2481                              <1> 	; 09/11/2015
  2482                              <1> 	;movzx	ebx, ax ; 8 or 9
  2483                              <1> 	; 08/01/2022
  2484 00003454 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2485                              <1> 	; 17/11/2015
  2486                              <1>  	; reset request for response status
  2487 00003456 88A3[5C6B0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2488                              <1> 	;
  2489                              <1> 	; 20/11/2015
  2490 0000345C EC                  <1> 	in	al, dx		; read interrupt id. register
  2491 0000345D EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2492 0000345F 2404                <1> 	and	al, 4		; received data available?	
  2493 00003461 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2494                              <1> 	;
  2495                              <1> 	; 20/11/2015
  2496 00003463 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2497 00003466 EC                  <1> 	in	al, dx     	; read character
  2498                              <1> 	;JMP	$+2	   	; I/O DELAY
  2499                              <1> 	; 08/11/2015
  2500                              <1> 	; 07/11/2015
  2501 00003467 89DE                <1> 	mov	esi, ebx 
  2502 00003469 89DF                <1> 	mov	edi, ebx
  2503 0000346B 81C6[606B0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2504 00003471 81C7[626B0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2505 00003477 8806                <1> 	mov	[esi], al ; received char (current char)
  2506                              <1> 	; query
  2507 00003479 20C0                <1> 	and	al, al
  2508 0000347B 7527                <1> 	jnz	short com_i2
  2509                              <1>    	; response
  2510                              <1> 	; 17/11/2015
  2511                              <1> 	; set request for response status
  2512 0000347D FE83[5C6B0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2513                              <1> 	;
  2514 00003483 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2515 00003487 EC                  <1> 	in	al, dx	   	; read line status register 
  2516 00003488 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2517 0000348A 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2518 0000348C 7445                <1> 	jz	short com_eoi 	; no
  2519 0000348E B0FF                <1> 	mov 	al, 0FFh   	; response			
  2520 00003490 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2521 00003494 EE                  <1> 	out	dx, al	   	; send on serial port
  2522                              <1> 	; 17/11/2015
  2523 00003495 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2524 00003498 7502                <1> 	jne 	short com_i1    ; no
  2525 0000349A 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2526                              <1> com_i1:
  2527                              <1> 	; 17/11/2015
  2528                              <1> 	; reset request for response status (again)
  2529 0000349C FE8B[5C6B0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2530 000034A2 EB2F                <1> 	jmp	short com_eoi
  2531                              <1> com_i2:	
  2532                              <1> 	; 08/11/2015
  2533 000034A4 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2534 000034A6 7417                <1> 	je	short com_i3	; (check for response signal)
  2535                              <1> 	; 07/11/2015
  2536 000034A8 3C04                <1> 	cmp	al, 04h	; EOT
  2537 000034AA 751C                <1> 	jne	short com_i4	
  2538                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2539                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2540                              <1> 	; 08/11/2015
  2541                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2542 000034AC 861D[266B0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2543 000034B2 E80BFFFFFF          <1> 	call 	ctrlbrk
  2544 000034B7 861D[266B0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2545                              <1> 	;mov	al, 04h ; EOT
  2546                              <1> 	; 08/11/2015
  2547 000034BD EB09                <1> 	jmp	short com_i4	
  2548                              <1> com_i3:
  2549                              <1> 	; 08/11/2015
  2550                              <1> 	; If 0FFh has been received just after a query
  2551                              <1> 	; (schar, ZERO), it is a response signal.
  2552                              <1> 	; 17/11/2015
  2553 000034BF 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2554 000034C2 7704                <1> 	ja	short com_i4 ; no
  2555                              <1> 	; reset query status (schar)
  2556 000034C4 8807                <1> 	mov	[edi], al ; 0FFh
  2557 000034C6 FEC0                <1> 	inc	al ; 0
  2558                              <1> com_i4:
  2559                              <1> 	; 27/07/2014
  2560                              <1> 	; 09/07/2014
  2561 000034C8 D0E3                <1> 	shl	bl, 1	
  2562 000034CA 81C3[286B0000]      <1> 	add	ebx, ttychr
  2563                              <1> 	; 23/07/2014 (always overwrite)
  2564                              <1> 	;;cmp	word [ebx], 0
  2565                              <1> 	;;ja	short com_eoi
  2566                              <1> 	;
  2567 000034D0 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2568                              <1> 			    ; scan code = 0
  2569                              <1> com_eoi:
  2570                              <1> 	;mov	al, 20h
  2571                              <1> 	;out	20h, al	   ; end of interrupt
  2572                              <1> 	;
  2573                              <1> 	; 07/11/2015
  2574                              <1>       	;pop	eax ; *
  2575 000034D3 A0[666B0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2576                              <1> 	; al = tty number (8 or 9)
  2577 000034D8 E8AD1A0000          <1>         call	wakeup
  2578                              <1> com_iret:
  2579                              <1> 	; 23/10/2015
  2580 000034DD 5A                  <1> 	pop	edx ; **
  2581 000034DE 59                  <1> 	pop	ecx ; ***
  2582                              <1> 	; 18/11/2015
  2583                              <1> 	;pop	eax ; ****
  2584                              <1> 	;mov	cr3, eax
  2585                              <1> 	;jmp	iiret
  2586 000034DF E9C1D4FFFF          <1> 	jmp	iiretp
  2587                              <1> 
  2588                              <1> ;iiretp: ; 01/09/2015
  2589                              <1> ;	; 28/08/2015
  2590                              <1> ;	pop	eax ; (*) page directory
  2591                              <1> ;	mov	cr3, eax
  2592                              <1> ;iiret:
  2593                              <1> ;	; 22/08/2014
  2594                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2595                              <1> ;	out	20h, al	; 8259 PORT
  2596                              <1> ;	;
  2597                              <1> ;	pop	es
  2598                              <1> ;	pop	ds
  2599                              <1> ;	pop	edi
  2600                              <1> ;	pop	esi
  2601                              <1> ;	pop	ebx ; 29/08/2014
  2602                              <1> ;	pop 	eax
  2603                              <1> ;	iretd
  2604                              <1> 
  2605                              <1> sp_init:
  2606                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2607                              <1> 	; 07/11/2015
  2608                              <1> 	; 29/10/2015
  2609                              <1> 	; 26/10/2015
  2610                              <1> 	; 23/10/2015
  2611                              <1> 	; 29/06/2015
  2612                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2613                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2614                              <1> 	; Initialization of Serial Port Communication Parameters
  2615                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2616                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2617                              <1> 	;
  2618                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2619                              <1> 	;
  2620                              <1> 	; INPUT:  (29/06/2015)
  2621                              <1> 	;	AL = 0 for COM1
  2622                              <1> 	;	     1 for COM2
  2623                              <1> 	;	AH = Communication parameters	
  2624                              <1> 	;
  2625                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2626                              <1> 	;	Bit	4	3	2	1	0
  2627                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2628                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2629                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2630                              <1> 	;		11 = even
  2631                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2632                              <1> 	;		Retro UNIX 386 v1 feature only !
  2633                              <1> 	;	Bit	7    6    5  | Baud rate
  2634                              <1> 	;		------------------------
  2635                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2636                              <1> 	;		0    0    1  | 9600 (12)
  2637                              <1> 	;		0    1    0  | 19200 (6) 
  2638                              <1> 	;		0    1	  1  | 38400 (3) 
  2639                              <1> 	;		1    0	  0  | 14400 (8)
  2640                              <1> 	;		1    0	  1  | 28800 (4)
  2641                              <1> 	;		1    1    0  | 57600 (2)
  2642                              <1> 	;		1    1    1  | 115200 (1) 	
  2643                              <1> 	
  2644                              <1> 	; References:	
  2645                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2646                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2647                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2648                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2649                              <1> 	;
  2650                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2651                              <1> 	;
  2652 000034E4 BB[626B0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2653 000034E9 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2654                              <1> 	; 29/10/2015
  2655 000034ED 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2656 000034F1 E84F000000          <1> 	call	sp_i3	; call A4	
  2657 000034F6 A880                <1> 	test	al, 80h
  2658 000034F8 740E                <1> 	jz	short sp_i0 ; OK..
  2659                              <1> 		; Error !
  2660                              <1> 	;mov	dx, 3F8h
  2661 000034FA 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2662                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2663                              <1> 	; 08/01/2022
  2664 000034FD B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2665 000034FF E841000000          <1> 	call	sp_i3	; call A4	
  2666 00003504 A880                <1> 	test	al, 80h
  2667 00003506 7508                <1> 	jnz	short sp_i1
  2668                              <1> sp_i0:
  2669                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2670                              <1>         ; (INT 14h initialization code disables interrupts.)
  2671                              <1> 	;
  2672 00003508 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2673 0000350B E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2674                              <1> sp_i1:
  2675 00003510 43                  <1> 	inc	ebx
  2676 00003511 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2677                              <1> 	; 29/10/2015
  2678                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2679                              <1> 	; 08/01/2022
  2680 00003515 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2681 00003517 E829000000          <1> 	call	sp_i3	; call A4	
  2682 0000351C A880                <1> 	test	al, 80h
  2683 0000351E 740E                <1> 	jz	short sp_i2 ; OK..
  2684                              <1> 		; Error !
  2685                              <1> 	;mov	dx, 2F8h
  2686 00003520 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2687                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2688                              <1> 	; 08/01/2022
  2689 00003523 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2690 00003525 E81B000000          <1> 	call	sp_i3	; call A4	
  2691 0000352A A880                <1> 	test	al, 80h
  2692 0000352C 7516                <1> 	jnz	short sp_i7
  2693                              <1> sp_i2:
  2694 0000352E C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2695                              <1> sp_i6:
  2696                              <1> 	;; COM2 - enabling IRQ 3
  2697                              <1> 	; 08/01/2022
  2698 00003531 B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2699                              <1> 	; 07/11/2015
  2700                              <1> 	; 26/10/2015
  2701                              <1> 	;pushf
  2702                              <1> 	;cli
  2703                              <1> 	;;
  2704                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2705                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2706                              <1> 	;in	al, dx 	   		; read register
  2707                              <1> 	;JMP	$+2	   		; I/O DELAY
  2708                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2709                              <1> 	;out	dx, al     		; write back to register
  2710                              <1> 	;JMP	$+2	   		; I/O DELAY
  2711                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2712                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2713                              <1> 	;in	al, dx     		; read register
  2714                              <1> 	;JMP	$+2	   		; I/O DELAY
  2715                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2716                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2717                              <1> 	;out	dx, al 	   		; write back to register
  2718                              <1> 	;JMP	$+2        		; I/O DELAY
  2719                              <1> 	;in	al, 21h    		; read interrupt mask register
  2720                              <1> 	;JMP	$+2	   		; I/O DELAY
  2721                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2722                              <1> 	;out	21h, al    		; write back to register
  2723                              <1> 	;
  2724                              <1> 	; 08/01/2022
  2725 00003533 9C                  <1> 	pushf
  2726 00003534 E8AA000000          <1> 	call	sp_i8
  2727                              <1> 	; 23/10/2015
  2728 00003539 B8[18340000]        <1> 	mov 	eax, com2_int
  2729 0000353E A3[D7390000]        <1> 	mov	[com2_irq3], eax
  2730                              <1> 	; 26/10/2015
  2731 00003543 9D                  <1> 	popf	
  2732                              <1> sp_i7:
  2733 00003544 C3                  <1> 	retn
  2734                              <1> 
  2735                              <1> sp_i3:
  2736                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2737                              <1> 	; 28/10/2015
  2738 00003545 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2739 00003547 B000                <1> 	mov	al, 0
  2740 00003549 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2741 0000354A EB00                <1> 	JMP	$+2			; I/O DELAY
  2742 0000354C 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2743 0000354F B080                <1> 	mov	al, 80h			
  2744 00003551 EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2745                              <1> 	;-----	SET BAUD RATE DIVISOR
  2746                              <1> 	; 26/10/2015
  2747 00003552 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2748                              <1> 					; of the divisor value
  2749 00003555 88C8                <1> 	mov	al, cl	; 1
  2750 00003557 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2751                              <1> 					; 2 = 57600 baud
  2752                              <1> 					; 3 = 38400 baud
  2753                              <1> 					; 6 = 19200 baud
  2754                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2755 00003558 EB00                <1> 	JMP	$+2			; I/O DELAY
  2756 0000355A 28C0                <1> 	sub	al, al
  2757 0000355C FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2758                              <1> 					; of the divisor value
  2759 0000355E EE                  <1> 	out	dx, al ; 0
  2760 0000355F EB00                <1> 	JMP	$+2			; I/O DELAY
  2761                              <1> 	;	
  2762 00003561 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2763                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2764 00003563 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2765 00003566 EE                  <1> 	out	dx, al			
  2766 00003567 EB00                <1> 	JMP	$+2			; I/O DELAY
  2767                              <1> 	; 29/10/2015
  2768 00003569 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2769 0000356B 30C0                <1> 	xor	al, al			; 0
  2770 0000356D EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2771 0000356E EB00                <1> 	JMP	$+2	
  2772                              <1> sp_i4:
  2773                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2774                              <1> 	; 29/06/2015 (line status after modem status)
  2775 00003570 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2776                              <1> sp_i4s:
  2777 00003573 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2778 00003574 EB00                <1> 	JMP	$+2			; I/O DELAY
  2779 00003576 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2780 00003578 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2781                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2782 0000357A EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2783                              <1> 	; AL = Line status, AH = Modem status
  2784 0000357B C3                  <1> 	retn
  2785                              <1> 
  2786                              <1> sp_status:
  2787                              <1> 	; 29/06/2015
  2788                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2789                              <1> 	; Get serial port status
  2790 0000357C 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2791 00003580 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2792                              <1> 					; dx = 2FEh for COM2
  2793 00003582 EBEF                <1> 	jmp	short sp_i4s
  2794                              <1> 
  2795                              <1> sp_setp: ; Set serial port communication parameters
  2796                              <1> 	; 08/01/2022
  2797                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2798                              <1> 	; 07/11/2015
  2799                              <1> 	; 29/10/2015
  2800                              <1> 	; 29/06/2015
  2801                              <1> 	; Retro UNIX 386 v1 feature only !	
  2802                              <1> 	;
  2803                              <1> 	; INPUT:
  2804                              <1> 	;	AL = 0 for COM1
  2805                              <1> 	;	     1 for COM2
  2806                              <1> 	;	AH = Communication parameters (*)
  2807                              <1> 	; OUTPUT:
  2808                              <1> 	;	CL = Line status
  2809                              <1> 	;	CH = Modem status
  2810                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2811                              <1> 	;		 'invalid parameter !' 
  2812                              <1> 	;		 	 or
  2813                              <1> 	;		 'device not ready !' error
  2814                              <1> 	;	
  2815                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2816                              <1> 	;	Bit	4	3	2	1	0
  2817                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2818                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2819                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2820                              <1> 	;		11 = even
  2821                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2822                              <1> 	;		Retro UNIX 386 v1 feature only !
  2823                              <1> 	;	Bit	7    6    5  | Baud rate
  2824                              <1> 	;		------------------------
  2825                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2826                              <1> 	;		0    0    1  | 9600 (12)
  2827                              <1> 	;		0    1    0  | 19200 (6) 
  2828                              <1> 	;		0    1	  1  | 38400 (3) 
  2829                              <1> 	;		1    0	  0  | 14400 (8)
  2830                              <1> 	;		1    0	  1  | 28800 (4)
  2831                              <1> 	;		1    1    0  | 57600 (2)
  2832                              <1> 	;		1    1    1  | 115200 (1) 
  2833                              <1> 	;
  2834                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2835                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2836                              <1> 	;
  2837                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2838                              <1> 	;
  2839 00003584 66BAF803            <1> 	mov	dx, 3F8h
  2840 00003588 BB[626B0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2841 0000358D 3C01                <1> 	cmp	al, 1
  2842 0000358F 7770                <1> 	ja 	short sp_invp_err
  2843 00003591 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2844 00003593 FECE                <1> 	dec	dh ; 2F8h
  2845 00003595 43                  <1> 	inc	ebx ; COM2 control byte offset
  2846                              <1> sp_setp1:
  2847                              <1> 	; 29/10/2015
  2848 00003596 8823                <1> 	mov	[ebx], ah
  2849 00003598 0FB6CC              <1> 	movzx 	ecx, ah
  2850 0000359B C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2851 0000359E 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2852 000035A1 8A81[10360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2853 000035A7 6689C1              <1> 	mov	cx, ax
  2854 000035AA E896FFFFFF          <1> 	call	sp_i3
  2855 000035AF 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2856 000035B2 A880                <1> 	test	al, 80h
  2857 000035B4 740F                <1> 	jz	short sp_setp2
  2858 000035B6 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2859                              <1> stp_dnr_err:
  2860 000035B9 C705[0D6F0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2860 000035C1 0000                <1>
  2861                              <1> 	; CL = Line status, CH = Modem status
  2862 000035C3 F9                  <1> 	stc
  2863 000035C4 C3                  <1> 	retn
  2864                              <1> sp_setp2:
  2865 000035C5 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2866                              <1>         ;jna	sp_i6
  2867                              <1> 		      ; COM1 (3F?h)
  2868                              <1> 	; 24/12/2021
  2869 000035C8 7705                <1> 	ja	short sp_i5
  2870 000035CA E962FFFFFF          <1> 	jmp	sp_i6
  2871                              <1> sp_i5: 
  2872                              <1> 	; 08/01/2022
  2873 000035CF B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2874                              <1> 	; 07/11/2015
  2875                              <1> 	; 26/10/2015
  2876                              <1> 	; 29/06/2015
  2877                              <1> 	;
  2878                              <1> 	;; COM1 - enabling IRQ 4
  2879                              <1> 	;pushf
  2880                              <1> 	;cli
  2881                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2882                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2883                              <1> 	;in	al, dx 	   		; read register
  2884                              <1> 	;JMP	$+2			; I/O DELAY
  2885                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2886                              <1> 	;out	dx, al     		; write back to register
  2887                              <1> 	;JMP	$+2			; I/O DELAY
  2888                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2889                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2890                              <1> 	;in	al, dx     		; read register
  2891                              <1> 	;JMP	$+2			; I/O DELAY
  2892                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2893                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2894                              <1> 	;out	dx, al 	   		; write back to register
  2895                              <1> 	;JMP	$+2        		; I/O DELAY
  2896                              <1> 	;in	al, 21h    		; read interrupt mask register
  2897                              <1> 	;JMP	$+2			; I/O DELAY
  2898                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2899                              <1> 	;out	21h, al    		; write back to register
  2900                              <1> 	;
  2901                              <1> 	; 08/01/2022
  2902 000035D1 9C                  <1> 	pushf
  2903 000035D2 E80C000000          <1> 	call	sp_i8
  2904                              <1> 	; 23/10/2015
  2905 000035D7 B8[21340000]        <1> 	mov 	eax, com1_int
  2906 000035DC A3[D3390000]        <1> 	mov	[com1_irq4], eax
  2907                              <1> 	; 26/10/2015
  2908 000035E1 9D                  <1> 	popf
  2909 000035E2 C3                  <1> 	retn
  2910                              <1> 
  2911                              <1> sp_i8:
  2912                              <1> 	; 08/01/2022
  2913                              <1> 	;pushf
  2914 000035E3 FA                  <1> 	cli
  2915                              <1> 	;
  2916                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2917 000035E4 B2FC                <1> 	mov	dl, 0FCh
  2918 000035E6 EC                  <1> 	in	al, dx 	   		; read register
  2919 000035E7 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2920 000035E9 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2921 000035EB EE                  <1> 	out	dx, al     		; write back to register
  2922 000035EC EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2923                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2924 000035EE B2F9                <1> 	mov	dl, 0F9h
  2925 000035F0 EC                  <1> 	in	al, dx     		; read register
  2926 000035F1 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2927                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2928 000035F3 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2929 000035F5 EE                  <1> 	out	dx, al 	   		; write back to register
  2930 000035F6 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2931 000035F8 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2932 000035FA EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2933                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2934 000035FC 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2935 000035FE E621                <1> 	out	21h, al    		; write back to register
  2936                              <1> 	;
  2937                              <1> 	;popf	
  2938 00003600 C3                  <1> 	retn
  2939                              <1> 
  2940                              <1> sp_invp_err:
  2941 00003601 C705[0D6F0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2941 00003609 0000                <1>
  2942 0000360B 31C9                <1> 	xor	ecx, ecx
  2943 0000360D 49                  <1> 	dec	ecx ; 0FFFFh
  2944 0000360E F9                  <1> 	stc
  2945 0000360F C3                  <1> 	retn
  2946                              <1> 
  2947                              <1> ; 29/10/2015
  2948                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2949 00003610 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2950                              <1> 
  2951                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2952                              <1> epoch:
  2953                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2954                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2955                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2956                              <1> 	; 'epoch' procedure prototype: 
  2957                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2958                              <1> 	; 14/11/2012
  2959                              <1> 	; unixboot.asm (boot file configuration)
  2960                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2961                              <1> 	; 21/7/2012
  2962                              <1> 	; 15/7/2012
  2963                              <1> 	; 14/7/2012		
  2964                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2965                              <1> 	; compute current date and time as UNIX Epoch/Time
  2966                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2967                              <1> 	;
  2968                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2969                              <1> 	;
  2970 00003617 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2971 0000361C 86E9                <1>         xchg 	ch,cl
  2972 0000361E 66890D[66680000]    <1>         mov 	[hour], cx
  2973 00003625 86F2                <1>         xchg 	dh,dl
  2974 00003627 668915[6A680000]    <1>         mov 	[second], dx
  2975                              <1> 	;
  2976 0000362E E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2977 00003633 86E9                <1>         xchg 	ch,cl
  2978 00003635 66890D[60680000]    <1>         mov 	[year], cx
  2979 0000363C 86F2                <1>         xchg 	dh,dl
  2980 0000363E 668915[62680000]    <1>         mov 	[month], dx
  2981                              <1> 	;
  2982 00003645 66B93030            <1> 	mov 	cx, 3030h
  2983                              <1> 	;
  2984 00003649 A0[66680000]        <1> 	mov 	al, [hour] ; Hour
  2985                              <1>         	; AL <= BCD number)
  2986 0000364E D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2987                              <1> 					; AH = AL / 10h
  2988                              <1> 					; AL = AL MOD 10h
  2989 00003650 D50A                <1>         aad 	; AX= AH*10+AL
  2990 00003652 A2[66680000]        <1> 	mov 	[hour], al
  2991 00003657 A0[67680000]        <1> 	mov 	al, [hour+1] ; Minute
  2992                              <1>         	; AL <= BCD number)
  2993 0000365C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2994                              <1> 					; AH = AL / 10h
  2995                              <1> 					; AL = AL MOD 10h
  2996 0000365E D50A                <1>         aad 	; AX= AH*10+AL
  2997 00003660 A2[68680000]        <1> 	mov 	[minute], al
  2998 00003665 A0[6A680000]        <1> 	mov 	al, [second] ; Second
  2999                              <1>         	; AL <= BCD number)
  3000 0000366A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3001                              <1> 					; AH = AL / 10h
  3002                              <1> 					; AL = AL MOD 10h
  3003 0000366C D50A                <1>         aad 	; AX= AH*10+AL
  3004 0000366E A2[6A680000]        <1> 	mov 	[second], al
  3005 00003673 66A1[60680000]      <1> 	mov 	ax, [year] ; Year (century)
  3006                              <1>  	;push 	ax
  3007                              <1> 	; 08/01/2022
  3008 00003679 50                  <1> 	push	eax
  3009                              <1> 	   	; AL <= BCD number)
  3010 0000367A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3011                              <1> 					; AH = AL / 10h
  3012                              <1> 					; AL = AL MOD 10h
  3013 0000367C D50A                <1>         aad 	; AX= AH*10+AL
  3014 0000367E B464                <1> 	mov 	ah, 100
  3015 00003680 F6E4                <1> 	mul 	ah
  3016 00003682 66A3[60680000]      <1> 	mov 	[year], ax
  3017                              <1> 	;pop	ax
  3018                              <1> 	; 08/01/2022
  3019 00003688 58                  <1> 	pop	eax
  3020 00003689 88E0                <1> 	mov	al, ah
  3021                              <1>         	; AL <= BCD number)
  3022 0000368B D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3023                              <1> 					; AH = AL / 10h
  3024                              <1> 					; AL = AL MOD 10h
  3025 0000368D D50A                <1>         aad 	; AX= AH*10+AL
  3026 0000368F 660105[60680000]    <1> 	add 	[year], ax
  3027 00003696 A0[62680000]        <1> 	mov 	al, [month] ; Month
  3028                              <1>            	; AL <= BCD number)
  3029 0000369B D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3030                              <1> 					; AH = AL / 10h
  3031                              <1> 					; AL = AL MOD 10h
  3032 0000369D D50A                <1>         aad 	; AX= AH*10+AL
  3033 0000369F A2[62680000]        <1> 	mov 	[month], al	
  3034 000036A4 A0[63680000]        <1>         mov     al, [month+1]      	; Day
  3035                              <1>            	; AL <= BCD number)
  3036 000036A9 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3037                              <1> 					; AH = AL / 10h
  3038                              <1> 					; AL = AL MOD 10h
  3039 000036AB D50A                <1>         aad 	; AX= AH*10+AL
  3040 000036AD A2[64680000]        <1>         mov     [day], al
  3041                              <1> 	
  3042                              <1> convert_to_epoch:
  3043                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3044                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3045                              <1> 	;
  3046                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3047                              <1> 	;
  3048                              <1> 	; Derived from DALLAS Semiconductor
  3049                              <1> 	; Application Note 31 (DS1602/DS1603)
  3050                              <1> 	; 6 May 1998
  3051 000036B2 29C0                <1> 	sub 	eax, eax
  3052 000036B4 66A1[60680000]      <1> 	mov 	ax, [year]
  3053 000036BA 662DB207            <1> 	sub 	ax, 1970
  3054 000036BE BA6D010000          <1> 	mov 	edx, 365
  3055 000036C3 F7E2                <1> 	mul 	edx
  3056 000036C5 31DB                <1> 	xor 	ebx, ebx
  3057 000036C7 8A1D[62680000]      <1> 	mov 	bl, [month]
  3058 000036CD FECB                <1> 	dec 	bl
  3059 000036CF D0E3                <1> 	shl 	bl, 1
  3060                              <1> 	;sub	edx, edx
  3061 000036D1 668B93[6C680000]    <1> 	mov 	dx, [EBX+DMonth]
  3062 000036D8 8A1D[64680000]      <1>         mov     bl, [day]
  3063 000036DE FECB                <1> 	dec 	bl
  3064 000036E0 01D0                <1> 	add 	eax, edx
  3065 000036E2 01D8                <1> 	add 	eax, ebx
  3066                              <1> 			; EAX = days since 1/1/1970
  3067 000036E4 668B15[60680000]    <1> 	mov 	dx, [year]
  3068 000036EB 6681EAB107          <1> 	sub 	dx, 1969
  3069 000036F0 66D1EA              <1> 	shr 	dx, 1
  3070 000036F3 66D1EA              <1> 	shr 	dx, 1		
  3071                              <1> 		; (year-1969)/4
  3072 000036F6 01D0                <1> 	add 	eax, edx
  3073                              <1> 			; + leap days since 1/1/1970
  3074 000036F8 803D[62680000]02    <1> 	cmp 	byte [month], 2	; if past february
  3075 000036FF 7610                <1> 	jna 	short cte1
  3076 00003701 668B15[60680000]    <1> 	mov 	dx, [year]
  3077 00003708 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3078 0000370C 7503                <1> 	jnz 	short cte1		
  3079                              <1> 			; and if leap year
  3080 0000370E 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3081                              <1> cte1: 			; compute seconds since 1/1/1970
  3082 00003711 BA18000000          <1> 	mov 	edx, 24
  3083 00003716 F7E2                <1> 	mul	edx
  3084 00003718 8A15[66680000]      <1> 	mov 	dl, [hour]
  3085 0000371E 01D0                <1> 	add 	eax, edx
  3086                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3087                              <1> 	;mov	ebx, 60
  3088 00003720 B33C                <1> 	mov	bl, 60
  3089 00003722 F7E3                <1> 	mul	ebx
  3090 00003724 8A15[68680000]      <1> 	mov 	dl, [minute]
  3091 0000372A 01D0                <1> 	add 	eax, edx
  3092                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3093                              <1> 	;mov 	ebx, 60
  3094 0000372C F7E3                <1> 	mul	ebx
  3095 0000372E 8A15[6A680000]      <1> 	mov 	dl, [second]
  3096 00003734 01D0                <1> 	add 	eax, edx
  3097                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3098 00003736 C3                  <1> 	retn
  3099                              <1> 
  3100                              <1> get_rtc_time:
  3101                              <1> 	; 15/03/2015
  3102                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3103                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3104                              <1> 	; INT 1Ah
  3105                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3106                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3107                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3108                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3109                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3110                              <1> 	;								
  3111                              <1> RTC_20: 				; GET RTC TIME
  3112 00003737 FA                  <1> 	cli
  3113 00003738 E804D4FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3114 0000373D 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3115                              <1> 
  3116 0000373F B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3117 00003741 E8E5D3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3118 00003746 88C6                <1> 	MOV	DH, AL			; SAVE
  3119 00003748 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3120 0000374A E8DCD3FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3121 0000374F 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3122 00003751 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3123 00003753 B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3124 00003755 E8D1D3FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3125 0000375A 88C1                <1> 	MOV	CL, AL			; SAVE
  3126 0000375C B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3127 0000375E E8C8D3FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3128 00003763 88C5                <1> 	MOV	CH, AL			; SAVE
  3129 00003765 F8                  <1> 	CLC				; SET CY= 0
  3130                              <1> RTC_29:
  3131 00003766 FB                  <1> 	sti
  3132 00003767 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3133                              <1> 
  3134                              <1> get_rtc_date:
  3135                              <1> 	; 15/03/2015
  3136                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3137                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3138                              <1> 	; INT 1Ah
  3139                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3140                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3141                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3142                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3143                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3144                              <1> 	;
  3145                              <1> RTC_40: 				; GET RTC DATE
  3146 00003768 FA                  <1> 	cli
  3147 00003769 E8D3D3FFFF          <1> 	CALL	UPD_IPR			; CHECK FOR UPDATE IN PROCESS
  3148 0000376E 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3149                              <1> 
  3150 00003770 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3151 00003772 E8B4D3FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3152 00003777 88C2                <1> 	MOV	DL, AL			; SAVE
  3153 00003779 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3154 0000377B E8ABD3FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3155 00003780 88C6                <1> 	MOV	DH, AL			; SAVE
  3156 00003782 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3157 00003784 E8A2D3FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3158 00003789 88C1                <1> 	MOV	CL, AL			; SAVE
  3159 0000378B B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3160 0000378D E899D3FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3161 00003792 88C5                <1> 	MOV	CH, AL			; SAVE
  3162 00003794 F8                  <1> 	CLC				; SET CY=0
  3163                              <1> RTC_49:
  3164 00003795 FB                  <1> 	sti
  3165 00003796 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3166                              <1> 
  3167                              <1> set_date_time:
  3168                              <1> convert_from_epoch:
  3169                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3170                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3171                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3172                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3173                              <1> 	;
  3174                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3175                              <1> 	;
  3176                              <1> 	; Derived from DALLAS Semiconductor
  3177                              <1> 	; Application Note 31 (DS1602/DS1603)
  3178                              <1> 	; 6 May 1998
  3179                              <1> 	;
  3180                              <1> 	; INPUT:
  3181                              <1> 	; EAX = Unix (Epoch) Time
  3182                              <1> 	;
  3183 00003797 31D2                <1> 	xor 	edx, edx
  3184 00003799 B93C000000          <1> 	mov 	ecx, 60
  3185 0000379E F7F1                <1> 	div	ecx
  3186                              <1> 	;mov 	[imin], eax  ; whole minutes
  3187                              <1> 			     ; since 1/1/1970
  3188 000037A0 668915[6A680000]    <1> 	mov 	[second], dx ; leftover seconds
  3189 000037A7 29D2                <1> 	sub 	edx, edx
  3190 000037A9 F7F1                <1> 	div	ecx
  3191                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3192                              <1> 	;		     ; since 1/1/1970
  3193 000037AB 668915[68680000]    <1> 	mov 	[minute], dx ; leftover minutes
  3194 000037B2 31D2                <1> 	xor	edx, edx
  3195                              <1> 	;mov 	cx, 24
  3196 000037B4 B118                <1> 	mov 	cl, 24
  3197 000037B6 F7F1                <1> 	div	ecx
  3198                              <1> 	;mov 	[iday], ax   ; whole days
  3199                              <1> 			     ; since 1/1/1970
  3200 000037B8 668915[66680000]    <1> 	mov 	[hour], dx   ; leftover hours
  3201 000037BF 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3202                              <1> 			     ; 1/1/1968 	
  3203                              <1> 	;mov 	[iday], ax
  3204 000037C4 50                  <1> 	push 	eax
  3205 000037C5 29D2                <1> 	sub	edx, edx
  3206 000037C7 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3207 000037CC F7F1                <1> 	div	ecx
  3208 000037CE 59                  <1> 	pop 	ecx
  3209                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3210 000037CF 6652                <1> 	push 	dx
  3211                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3212 000037D1 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3213 000037D5 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3214 000037D6 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3215                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3216                              <1> 	;mov 	cx, [iday]
  3217 000037D9 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3218 000037DA 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3219 000037DC B96D010000          <1> 	mov 	ecx, 365
  3220 000037E1 31D2                <1> 	xor	edx, edx
  3221                              <1> 	; EAX = iday-lday, EDX = 0
  3222 000037E3 F7F1                <1> 	div	ecx
  3223                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3224                              <1> 	;jday = iday - (iyrs*365) - lday
  3225                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3226                              <1> 	;add	eax, 1968
  3227 000037E5 6605B007            <1> 	add 	ax, 1968     ; compute year
  3228 000037E9 66A3[60680000]      <1> 	mov 	[year], ax
  3229 000037EF 6689D1              <1> 	mov 	cx, dx
  3230                              <1> 	;mov 	dx, [qday]
  3231 000037F2 665A                <1> 	pop 	dx
  3232 000037F4 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3233 000037F9 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3234 000037FB 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3235 000037FF F5                  <1>         cmc		     ; add a leap day to the # of whole
  3236 00003800 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3237                              <1> cfe1:			
  3238                              <1> 	;mov 	[jday], cx
  3239 00003804 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3240 00003808 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3241 0000380C 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3242                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3243 00003810 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3244 00003813 731D                <1> 	jnb 	short cfe3
  3245 00003815 664B                <1> 	dec 	bx           ; month = month - 1
  3246 00003817 66D1E3              <1> 	shl 	bx, 1 
  3247 0000381A 668B93[6C680000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3248 00003821 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3249 00003824 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3250 00003828 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3251 0000382A 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3252 0000382C 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3253 0000382E 6642                <1> 	inc 	dx           ; mday = mday + 1
  3254 00003830 EBDE                <1> 	jmp 	short cfe2
  3255                              <1> cfe3:
  3256 00003832 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3257 00003834 66891D[62680000]    <1> 	mov 	[month], bx
  3258 0000383B 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3259 0000383E 6641                <1> 	inc 	cx 			  
  3260 00003840 66890D[64680000]    <1> 	mov 	[day], cx
  3261                              <1> 	
  3262                              <1> 	; eax, ebx, ecx, edx is changed at return
  3263                              <1> 	; output ->
  3264                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3265                              <1> 	
  3266                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3267                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3268                              <1> set_date:
  3269 00003847 A0[61680000]        <1>         mov     al, [year+1]
  3270 0000384C D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3271 0000384E D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3272                              <1> 			     ; AL = AH * 10h + AL
  3273 00003850 88C5                <1> 	mov 	ch, al ; century (BCD)
  3274 00003852 A0[60680000]        <1> 	mov 	al, [year]
  3275 00003857 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3276 00003859 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3277                              <1> 			     ; AL = AH * 10h + AL
  3278 0000385B 88C1                <1> 	mov 	cl, al ; year (BCD)
  3279 0000385D A0[62680000]        <1>         mov 	al, [month]
  3280 00003862 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3281 00003864 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3282                              <1> 			     ; AL = AH * 10h + AL
  3283 00003866 88C6                <1> 	mov 	dh, al ; month (BCD)
  3284 00003868 A0[64680000]        <1> 	mov 	al, [day]
  3285 0000386D D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3286 0000386F D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3287                              <1> 			     ; AL = AH * 10h + AL
  3288 00003871 88C6                <1> 	mov 	dh, al ; day (BCD)
  3289                              <1> 	; Set real-time clock date
  3290 00003873 E879000000          <1> 	call	set_rtc_date
  3291                              <1> set_time:
  3292                              <1>         ; Read real-time clock time 
  3293                              <1> 	; (get day light saving time bit status)
  3294 00003878 FA                  <1>  	cli
  3295 00003879 E8C3D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3296                              <1> 	; cf = 1 -> al = 0
  3297 0000387E 7207                <1>         jc      short stime1
  3298 00003880 B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3299 00003882 E8A4D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3300                              <1> stime1:
  3301 00003887 FB                  <1> 	sti
  3302 00003888 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3303 0000388A 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3304                              <1> 	; DL = 1 or 0 (day light saving time)
  3305                              <1> 	;	
  3306 0000388C A0[66680000]        <1> 	mov 	al, [hour]
  3307 00003891 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3308 00003893 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3309                              <1> 			     ; AL = AH * 10h + AL
  3310 00003895 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3311 00003897 A0[68680000]        <1>         mov     al, [minute]
  3312 0000389C D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3313 0000389E D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3314                              <1> 			     ; AL = AH * 10h + AL
  3315 000038A0 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3316 000038A2 A0[6A680000]        <1>         mov     al, [second]
  3317 000038A7 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3318 000038A9 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3319                              <1> 			     ; AL = AH * 10h + AL
  3320 000038AB 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3321                              <1> 	; Set real-time clock time
  3322                              <1>  	; call	set_rtc_time
  3323                              <1> set_rtc_time:
  3324                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3325                              <1> 	; 15/03/2015
  3326                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3327                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3328                              <1> 	; INT 1Ah
  3329                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3330                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3331                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3332                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3333                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3334                              <1> 	;								:
  3335                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3336                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3337                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3338                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3339                              <1> 	;
  3340                              <1> RTC_30: 				; SET RTC TIME
  3341 000038AD FA                  <1> 	cli
  3342 000038AE E88ED2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3343 000038B3 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3344 000038B5 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3345                              <1> RTC_35:
  3346 000038BA 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3347 000038BC B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3348 000038BE E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3349 000038C3 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3350 000038C5 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3351 000038C7 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3352 000038CC 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3353 000038CE B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3354 000038D0 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3355                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3356 000038D5 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3357 000038D9 E84DD2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3358 000038DE 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3359 000038E0 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3360 000038E2 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3361 000038E5 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3362 000038E7 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3363 000038E9 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3364 000038EE F8                  <1> 	CLC				; SET CY= 0
  3365 000038EF FB                  <1> 	sti
  3366 000038F0 C3                  <1> 	RETn				; RETURN WITH CY= 0
  3367                              <1> 
  3368                              <1> set_rtc_date:
  3369                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3370                              <1> 	; 15/03/2015
  3371                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3372                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3373                              <1> 	; INT 1Ah
  3374                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3375                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3376                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3377                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3378                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3379                              <1> 	;
  3380                              <1> RTC_50: 				; SET RTC DATE
  3381 000038F1 FA                  <1> 	cli
  3382 000038F2 E84AD2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3383 000038F7 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3384 000038F9 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3385                              <1> RTC_55:
  3386 000038FE 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3387 00003902 E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3388 00003907 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3389 00003909 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3390 0000390B E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3391 00003910 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3392 00003912 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3393 00003914 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3394 00003919 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3395 0000391B B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3396 0000391D E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3397 00003922 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3398 00003924 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3399 00003926 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3400                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3401 0000392B 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3402 0000392F E8F7D1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3403 00003934 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3404 00003936 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3405 00003938 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3406 0000393D F8                  <1> 	CLC				; SET CY= 0
  3407 0000393E FB                  <1> 	sti
  3408 0000393F C3                  <1> 	RETn				; RETURN CY=0
  3409                              <1> 
  3410                              <1> 	; 15/03/2015
  3411                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3412 00003940 B426                <1> 	mov	ah, 26h
  3413 00003942 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3414 00003944 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3415 00003949 B482                <1> 	mov	ah, 82h
  3416 0000394B B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3417 0000394D E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3418 00003952 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3419 00003954 E8D2D1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3420 00003959 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3421                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3422                              <1> 	;RETn
  3423                              <1> 	; 12/01/2022
  3424 0000395B E9CBD1FFFF          <1> 	jmp	CMOS_READ
  3425                              <1> 
  3426                              <1> 	; 15/03/2015
  3427                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3428                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3429 00003960 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3430                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3431 00003961 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3432 00003963 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3433 00003964 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3434 00003966 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3435 00003967 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3436 00003969 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3437 0000396B E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3438 0000396D B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3439 0000396F D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3440 00003971 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3441 00003973 90                  <1> 	nop			; I/O DELAY
  3442 00003974 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3443                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3444 00003976 9D                  <1> 	popf	
  3445 00003977 C3                  <1> 	RETn
  3446                              <1> 
  3447                              <1> bf_init:
  3448                              <1> 	; 14/08/2015
  3449                              <1> 	; 02/07/2015
  3450                              <1> 	; 01/07/2015
  3451                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3452                              <1> 	; Buffer (pointer) initialization !
  3453                              <1> 	; 
  3454                              <1> 	; 17/07/2013 - 24/07/2013
  3455                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3456                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3457                              <1> 	;
  3458 00003978 BF[7C6E0000]        <1> 	mov	edi, bufp 
  3459 0000397D B8[707B0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3460 00003982 29D2                <1> 	sub	edx, edx
  3461 00003984 FECA                <1> 	dec	dl
  3462 00003986 31C9                <1> 	xor	ecx, ecx
  3463 00003988 49                  <1> 	dec	ecx
  3464                              <1> bi0:
  3465 00003989 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3466 0000398E AB                  <1> 	stosd
  3467 0000398F 89C6                <1> 	mov	esi, eax
  3468 00003991 8916                <1> 	mov	[esi], edx ; 000000FFh
  3469                              <1> 			   ; Not a valid device sign
  3470 00003993 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3471                              <1> 		      ; Not a valid block number sign 	 	
  3472 00003996 3D[406F0000]        <1> 	cmp	eax, buffer
  3473 0000399B 77EC                <1> 	ja	short bi0
  3474 0000399D B8[707B0000]        <1> 	mov	eax, sb0
  3475 000039A2 AB                  <1> 	stosd
  3476 000039A3 B8[787D0000]        <1> 	mov	eax, sb1
  3477 000039A8 AB                  <1> 	stosd
  3478 000039A9 89C6                <1> 	mov	esi, eax ; offset sb1
  3479 000039AB 8916                <1> 	mov	[esi], edx ; 000000FFh
  3480                              <1> 			   ; Not a valid device sign
  3481 000039AD 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3482                              <1> 		      ; Not a valid block number sign 	 
  3483                              <1> 	; 14/08/2015
  3484                              <1> 	;call 	rdev_init
  3485                              <1> 	;retn
  3486                              <1> 
  3487                              <1> rdev_init: ; root device, super block buffer initialization
  3488                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3489                              <1> 	; 14/08/2015
  3490                              <1> 	; Retro UNIX 386 v1 feature only !
  3491                              <1> 	;
  3492                              <1> 	; NOTE: Disk partitions (file systems), logical
  3493                              <1> 	; drive initialization, partition's start sector etc.
  3494                              <1> 	; will be coded here, later in 'ldrv_init'	
  3495                              <1> 
  3496 000039B0 0FB605[EA650000]    <1> 	movzx	eax, byte [boot_drv]
  3497                              <1> rdi_0:
  3498 000039B7 3C80                <1> 	cmp	al, 80h
  3499 000039B9 7202                <1> 	jb	short rdi_1
  3500 000039BB 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3501                              <1> rdi_1:
  3502 000039BD A2[A06E0000]        <1> 	mov	[rdev], al
  3503 000039C2 BB[707B0000]        <1>         mov	ebx, sb0 ; super block buffer
  3504 000039C7 8903                <1> 	mov 	[ebx], eax
  3505 000039C9 B001                <1> 	mov	al, 1 ; eax = 1
  3506 000039CB 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3507                              <1> 	;call 	diskio
  3508                              <1> 	;retn
  3509                              <1> 	; 24/12/2021
  3510 000039CE E97D240000          <1> 	jmp	diskio
  3511                              <1> 
  3512                              <1> ; 23/10/2015
  3513                              <1> com1_irq4:
  3514 000039D3 [DB390000]          <1> 	dd	dummy_retn
  3515                              <1> com2_irq3:
  3516 000039D7 [DB390000]          <1> 	dd	dummy_retn
  3517                              <1> 
  3518                              <1> dummy_retn:
  3519 000039DB C3                  <1> 	retn
  2088                                  %include 'u1.s'        ; 10/05/2015
  2089                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS1.INC
  2090                              <1> ; Last Modification: 26/02/2022
  2091                              <1> ; ----------------------------------------------------------------------------
  2092                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2093                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2094                              <1> ;
  2095                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2096                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2097                              <1> ; <Bell Laboratories (17/3/1972)>
  2098                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2099                              <1> ;
  2100                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2101                              <1> ;
  2102                              <1> ; ****************************************************************************
  2103                              <1> 
  2104                              <1> unkni: ; / used for all system calls
  2105                              <1> sysent: ; < enter to system call >
  2106                              <1> 	; 08/01/2022
  2107                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2108                              <1> 	; 19/10/2015
  2109                              <1> 	; 21/09/2015
  2110                              <1> 	; 01/07/2015
  2111                              <1> 	; 19/05/2015
  2112                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2113                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2114                              <1> 	;
  2115                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2116                              <1> 	; The trap type is determined and an indirect jump is made to 
  2117                              <1> 	; the appropriate system call handler. If there is a trap inside
  2118                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2119                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2120                              <1> 	; instructor is decoded to get the the system code part (see
  2121                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2122                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2123                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2124                              <1> 	; is called. If the call is legitimate control passes to the
  2125                              <1> 	; appropriate system routine.
  2126                              <1> 	;
  2127                              <1> 	; Calling sequence:
  2128                              <1> 	;	Through a trap caused by any sys call outside the system.
  2129                              <1> 	; Arguments:
  2130                              <1> 	;	Arguments of particular system call.	
  2131                              <1> 	; ...............................................................
  2132                              <1> 	;	
  2133                              <1> 	; Retro UNIX 8086 v1 modification: 
  2134                              <1> 	;       System call number is in EAX register.
  2135                              <1> 	;
  2136                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2137                              <1> 	;	registers depending of function details.
  2138                              <1>   	;
  2139                              <1> 	; 16/04/2015
  2140 000039DC 368925[B06E0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2141                              <1> 	; save user registers
  2142 000039E3 1E                  <1> 	push	ds
  2143 000039E4 06                  <1> 	push	es
  2144 000039E5 0FA0                <1> 	push	fs
  2145 000039E7 0FA8                <1> 	push	gs
  2146 000039E9 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2147                              <1> 	;
  2148                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2149                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2150                              <1> 	;	for saving/restoring user registers.)
  2151                              <1> 	;
  2152 000039EA 50                  <1> 	push	eax ; 01/07/2015
  2153 000039EB 66B81000            <1> 	mov     ax, KDATA
  2154 000039EF 8ED8                <1>         mov     ds, ax
  2155 000039F1 8EC0                <1>         mov     es, ax
  2156 000039F3 8EE0                <1>         mov     fs, ax
  2157 000039F5 8EE8                <1>         mov     gs, ax
  2158 000039F7 A1[F86A0000]        <1> 	mov	eax, [k_page_dir]
  2159 000039FC 0F22D8              <1> 	mov	cr3, eax
  2160 000039FF 58                  <1> 	pop	eax ; 01/07/2015
  2161                              <1> 	; 19/10/2015
  2162 00003A00 FC                  <1> 	cld
  2163                              <1> 	;
  2164 00003A01 FE05[AF6E0000]      <1> 	inc	byte [sysflg]
  2165                              <1> 		; incb sysflg / indicate a system routine is in progress
  2166 00003A07 FB                  <1>         sti 	; 18/01/2014
  2167                              <1> 	;jnz	panic ; 24/05/2013
  2168                              <1> 	; 24/12/2021
  2169 00003A08 7405                <1> 	jz	short _1
  2170 00003A0A E979F9FFFF          <1> 	jmp	panic
  2171                              <1> 		; beq 1f
  2172                              <1> 		; jmp panic ; / called if trap inside system
  2173                              <1> ;1:
  2174                              <1> _1:	; 24/12/2021
  2175                              <1> 	; 16/04/2015
  2176 00003A0F A3[B86E0000]        <1> 	mov	[u.r0], eax
  2177 00003A14 8925[B46E0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2178                              <1> 	;
  2179                              <1> 		; mov $s.syst+2,clockp
  2180                              <1> 		; mov r0,-(sp) / save user registers 
  2181                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2182                              <1> 			   ; / in u.r0
  2183                              <1> 		; mov r1,-(sp)
  2184                              <1> 		; mov r2,-(sp)
  2185                              <1> 		; mov r3,-(sp)
  2186                              <1> 		; mov r4,-(sp)
  2187                              <1> 		; mov r5,-(sp)
  2188                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2189                              <1> 		             ; / arithmetic unit
  2190                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2191                              <1> 		             ; / extended arithmetic unit
  2192                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2193                              <1> 		             ; / arithmetic unit
  2194                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2195                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2196                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2197                              <1> 		; sub $sys,r0 / get xxx code
  2198 00003A1A C1E002              <1> 	shl	eax, 2
  2199                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2200 00003A1D 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2201                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2202                              <1> 	;jnb	short badsys
  2203                              <1> 		; bhis badsys / yes, bad system call
  2204                              <1> 	; 08/01/2022
  2205 00003A22 7205                <1> 	jb	short _2
  2206 00003A24 E95D010000          <1> 	jmp	badsys
  2207                              <1> _2:
  2208                              <1> 	; 08/01/2022
  2209                              <1> 	;cmc
  2210                              <1> 	;pushf	
  2211                              <1> 	;push	eax
  2212 00003A29 8B2D[B06E0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2213                              <1> 	;mov	al, 0FEh ; 11111110b
  2214                              <1> 	;;adc	al, 0 ; al = al + cf
  2215                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2216 00003A2F 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2217                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2218                              <1> 				 ; / and clear carry bit
  2219                              <1> 	;pop	ebp ; eax
  2220 00003A33 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2221                              <1> 	;popf
  2222                              <1>         ;;jc	badsys
  2223                              <1> 	; 24/12/2021
  2224                              <1> 	;jnc	short _3  ; 08/01/2022
  2225                              <1> 	;jmp	badsys
  2226                              <1> ;_3:
  2227 00003A35 A1[B86E0000]        <1> 	mov	eax, [u.r0]
  2228                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2229 00003A3A FFA5[403A0000]      <1> 	jmp	dword [ebp+syscalls]
  2230                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2231                              <1> 		            ; / to proper system routine.
  2232                              <1> syscalls: ; 1:
  2233                              <1> 	; 21/09/2015
  2234                              <1> 	; 01/07/2015
  2235                              <1> 	; 16/04/2015 (32 bit address modification) 
  2236 00003A40 [503B0000]          <1> 	dd sysrele	; / 0
  2237 00003A44 [F83B0000]          <1> 	dd sysexit 	; / 1
  2238 00003A48 [233D0000]          <1> 	dd sysfork 	; / 2
  2239 00003A4C [293E0000]          <1> 	dd sysread 	; / 3
  2240 00003A50 [3C3E0000]          <1> 	dd syswrite 	; / 4
  2241 00003A54 [A53E0000]          <1> 	dd sysopen 	; / 5
  2242 00003A58 [D03F0000]          <1> 	dd sysclose 	; / 6
  2243 00003A5C [9E3C0000]          <1> 	dd syswait 	; / 7
  2244 00003A60 [4D3F0000]          <1> 	dd syscreat 	; / 8
  2245 00003A64 [89430000]          <1> 	dd syslink 	; / 9
  2246 00003A68 [45440000]          <1> 	dd sysunlink 	; / 10
  2247 00003A6C [0F450000]          <1> 	dd sysexec 	; / 11
  2248 00003A70 [3D4B0000]          <1> 	dd syschdir 	; / 12
  2249 00003A74 [1D4C0000]          <1> 	dd systime 	; / 13
  2250 00003A78 [893F0000]          <1> 	dd sysmkdir 	; / 14
  2251 00003A7C [8D4B0000]          <1> 	dd syschmod 	; / 15
  2252 00003A80 [ED4B0000]          <1> 	dd syschown 	; / 16
  2253 00003A84 [504C0000]          <1> 	dd sysbreak 	; / 17
  2254 00003A88 [CC480000]          <1> 	dd sysstat 	; / 18
  2255 00003A8C [204D0000]          <1> 	dd sysseek 	; / 19
  2256 00003A90 [324D0000]          <1> 	dd systell 	; / 20
  2257 00003A94 [EF570000]          <1> 	dd sysmount 	; / 21
  2258 00003A98 [CE580000]          <1> 	dd sysumount 	; / 22
  2259 00003A9C [AE4D0000]          <1> 	dd syssetuid 	; / 23
  2260 00003AA0 [DF4D0000]          <1> 	dd sysgetuid 	; / 24
  2261 00003AA4 [2C4C0000]          <1> 	dd sysstime 	; / 25
  2262 00003AA8 [A24D0000]          <1> 	dd sysquit 	; / 26
  2263 00003AAC [964D0000]          <1> 	dd sysintr 	; / 27
  2264 00003AB0 [A9480000]          <1> 	dd sysfstat 	; / 28
  2265 00003AB4 [ED3F0000]          <1> 	dd sysemt 	; / 29
  2266 00003AB8 [39400000]          <1> 	dd sysmdate 	; / 30
  2267 00003ABC [93400000]          <1> 	dd sysstty 	; / 31
  2268 00003AC0 [7C420000]          <1> 	dd sysgtty 	; / 32
  2269 00003AC4 [34400000]          <1> 	dd sysilgins 	; / 33
  2270 00003AC8 [09610000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2271                              <1> 			     ; 11/06/2014
  2272 00003ACC [36610000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2273                              <1> 			     ; 01/07/2015
  2274 00003AD0 [0E620000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2275                              <1> 			     ; 21/09/2015 - get last error number
  2276                              <1> end_of_syscalls:
  2277                              <1> 
  2278                              <1> error:
  2279                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2280                              <1> 	; 17/09/2015
  2281                              <1> 	; 03/09/2015
  2282                              <1> 	; 01/09/2015
  2283                              <1> 	; 09/06/2015
  2284                              <1> 	; 13/05/2015
  2285                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2286                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2287                              <1> 	;
  2288                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2289                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2290                              <1> 	;
  2291                              <1> 	; INPUTS -> none
  2292                              <1> 	; OUTPUTS ->
  2293                              <1> 	;	processor status - carry (c) bit is set (means error)
  2294                              <1> 	;
  2295                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2296                              <1> 	; 	      Because, jumps to error procedure
  2297                              <1> 	;	      disrupts push-pop nesting balance)
  2298                              <1> 	;
  2299 00003AD4 8B2D[B06E0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2300 00003ADA 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2301                              <1> 				 ; (system call will return with cf = 1)
  2302                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2303                              <1> 		               ; / users stack
  2304                              <1> 	; 17/09/2015
  2305 00003ADE 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2306                              <1> 				 ; for saving/restoring user registers	
  2307                              <1> 	;cmp	ebp, [u.usp]
  2308                              <1> 	;je	short err0	
  2309 00003AE1 892D[B46E0000]      <1> 	mov	[u.usp], ebp
  2310                              <1> ;err0:
  2311                              <1> 	; 01/09/2015
  2312 00003AE7 8B25[B46E0000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2313                              <1> 				    ; 10/04/2013
  2314                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2315                              <1> 				    ; related procedures will jump to 'error'
  2316                              <1> 				    ; procedure directly without returning to 
  2317                              <1> 				    ; the caller procedure. So, stack pointer
  2318                              <1>                                     ; must be restored here.)
  2319                              <1> 	; 13/05/2015
  2320                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2321                              <1> 	;	'get last error' system call later. 	
  2322                              <1> 
  2323                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2324 00003AED C605[1F6F0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2325                              <1> 
  2326                              <1> sysret: ; < return from system call>
  2327                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2328                              <1> 	; 10/09/2015
  2329                              <1> 	; 29/07/2015
  2330                              <1> 	; 25/06/2015
  2331                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2332                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2333                              <1> 	;
  2334                              <1> 	; 'sysret' first checks to see if process is about to be 
  2335                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2336                              <1> 	; If not, following happens:	 
  2337                              <1> 	; 	1) The user's stack pointer is restored.
  2338                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2339                              <1> 	;	   i-node has been modified. If it has, it is written out
  2340                              <1> 	;	   via 'ppoke'.
  2341                              <1> 	;	3) If the super block has been modified, it is written out
  2342                              <1> 	;	   via 'ppoke'.				
  2343                              <1> 	;	4) If the dismountable file system's super block has been
  2344                              <1> 	;	   modified, it is written out to the specified device
  2345                              <1> 	;	   via 'ppoke'.
  2346                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2347                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2348                              <1> 	;	   another user a chance to run.
  2349                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2350                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2351                              <1> 	;
  2352                              <1> 	; Calling sequence:
  2353                              <1> 	;	jump table or 'br sysret'
  2354                              <1> 	; Arguments: 
  2355                              <1> 	;	-	
  2356                              <1> 	; ...............................................................
  2357                              <1> 	;	
  2358                              <1> 	; ((AX=r1 for 'iget' input))
  2359                              <1> 	;	
  2360                              <1> 	;xor	ax, ax ; 04/05/2013
  2361                              <1> 	; 24/12/2021
  2362 00003AF4 31C0                <1> 	xor	eax, eax
  2363                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2364 00003AF6 FEC0                <1> 	inc	al ; 04/05/2013
  2365 00003AF8 3805[066F0000]      <1> 	cmp	[u.bsys], al ; 1
  2366                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2367                              <1> 	;jnb	sysexit ; 04/05/2013
  2368                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2369                              <1> 	; 24/12/2021
  2370 00003AFE 720F                <1> 	jb	short _3
  2371 00003B00 C705[0D6F0000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2371 00003B08 0000                <1>
  2372 00003B0A E9E9000000          <1> 	jmp	sysexit
  2373                              <1> _3:
  2374                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2375                              <1> 		; mov u.sp,sp / no point stack to users stack
  2376 00003B0F FEC8                <1> 	dec 	al ; mov ax, 0
  2377                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2378 00003B11 E881160000          <1> 	call	iget
  2379                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2380                              <1> 		            ; / it is written out
  2381                              <1> 	;xor 	ax, ax ; 0
  2382                              <1> 	; 24/12/2021
  2383 00003B16 31C0                <1> 	xor	eax, eax
  2384 00003B18 3805[AD6E0000]      <1> 	cmp	[smod], al ; 0
  2385                              <1> 		; tstb	smod / has the super block been modified
  2386 00003B1E 7614                <1> 	jna	short sysret1
  2387                              <1> 		; beq	1f / no, 1f
  2388 00003B20 A2[AD6E0000]        <1> 	mov	[smod], al ; 0
  2389                              <1> 		; clrb smod / yes, clear smod
  2390 00003B25 BB[707B0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2391 00003B2A 66810B0002          <1>    	or	word [ebx], 200h ;;
  2392                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2393                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2394                              <1> 		      	      ; / output
  2395                              <1> 	; AX = 0
  2396 00003B2F E804220000          <1> 	call 	poke ; 07/08/2013
  2397                              <1> 	; call	ppoke
  2398                              <1> 	; AX = 0
  2399                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2400                              <1> sysret1: ;1:
  2401 00003B34 3805[AE6E0000]      <1> 	cmp	[mmod], al ; 0
  2402                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2403                              <1> 		           ; / system
  2404 00003B3A 7614                <1> 	jna	short sysrel0
  2405                              <1> 		; beq 1f / been modified?  no, 1f
  2406 00003B3C A2[AE6E0000]        <1> 	mov	[mmod], al ; 0	
  2407                              <1> 		; clrb	mmod / yes, clear mmod
  2408                              <1>         ;mov    ax, [mntd]
  2409                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2410 00003B41 BB[787D0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2411                              <1>         ;;mov	[ebx], al
  2412                              <1> 	;mov    [sb1], al
  2413                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2414 00003B46 66810B0002          <1> 	or	word [ebx], 200h
  2415                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2416                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2417 00003B4B E8E8210000          <1> 	call	poke ; 07/08/2013
  2418                              <1> 	;call	ppoke 
  2419                              <1> 		; jsr r0,ppoke / write it out to its device
  2420                              <1>         ;xor    al, al ; 26/04/2013       
  2421                              <1> ;1:
  2422                              <1> 		; tstb uquant / is the time quantum 0?
  2423                              <1> 		; bne 1f / no, don't swap it out
  2424                              <1> 
  2425                              <1> sysrele: ; < release >
  2426                              <1> 	; 14/10/2015
  2427                              <1> 	; 01/09/2015
  2428                              <1> 	; 24/07/2015
  2429                              <1> 	; 14/05/2015
  2430                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2431                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2432                              <1> 	;
  2433                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2434                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2435                              <1> 	; turns off the system flag. It then checked to see if there is
  2436                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2437                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2438                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2439                              <1> 	; the user, a rti is made.
  2440                              <1> 	;
  2441                              <1> 	; Calling sequence:
  2442                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2443                              <1> 	; Arguments:
  2444                              <1> 	;	-	
  2445                              <1> 	; ...............................................................
  2446                              <1> 	;	
  2447                              <1> 	; 23/02/2014 (swapret)
  2448                              <1> 	; 22/09/2013
  2449                              <1> sysrel0: ;1:
  2450 00003B50 803D[FA6E0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2451                              <1> 		; tstb uquant / is the time quantum 0?
  2452 00003B57 7705                <1>         ja      short swapret
  2453                              <1> 		; bne 1f / no, don't swap it out
  2454                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2455 00003B59 E8D1120000          <1> 	call	tswap
  2456                              <1> 		; jsr r0,tswap / yes, swap it out
  2457                              <1> ;
  2458                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2459                              <1> swapret: ;1:
  2460                              <1> 	; 10/09/2015
  2461                              <1> 	; 01/09/2015
  2462                              <1> 	; 14/05/2015
  2463                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2464                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2465                              <1> 	; cli
  2466                              <1> 	; 24/07/2015
  2467                              <1> 	;
  2468                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2469                              <1> 	;; mov	esp, [u.usp]
  2470                              <1> 
  2471                              <1> 	; 22/09/2013
  2472 00003B5E E8A3140000          <1> 	call	isintr
  2473                              <1> 	; 20/10/2013
  2474 00003B63 7405                <1> 	jz	short sysrel1
  2475 00003B65 E877000000          <1> 	call	intract
  2476                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2477                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2478                              <1> 		               ; / action
  2479                              <1> sysrel1:
  2480 00003B6A FA                  <1> 	cli ; 14/10/2015
  2481 00003B6B FE0D[AF6E0000]      <1> 	dec	byte [sysflg]
  2482                              <1> 		; decb sysflg / turn system flag off
  2483 00003B71 A1[116F0000]        <1> 	mov     eax, [u.pgdir]
  2484 00003B76 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2485                              <1> 			  ; (others are different than kernel page tables) 
  2486                              <1> 	; 10/09/2015
  2487 00003B79 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2488                              <1> 		; mov (sp)+,sc / restore user registers
  2489                              <1> 		; mov (sp)+,mq
  2490                              <1> 		; mov (sp)+,ac
  2491                              <1> 		; mov (sp)+,r5
  2492                              <1> 		; mov (sp)+,r4
  2493                              <1> 		; mov (sp)+,r3
  2494                              <1> 		; mov (sp)+,r2
  2495                              <1> 	;
  2496 00003B7A A1[B86E0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2497 00003B7F 0FA9                <1> 	pop	gs
  2498 00003B81 0FA1                <1> 	pop	fs
  2499 00003B83 07                  <1> 	pop	es
  2500 00003B84 1F                  <1> 	pop	ds
  2501 00003B85 CF                  <1> 	iretd	
  2502                              <1> 		; rti / no, return from interrupt
  2503                              <1> 
  2504                              <1> badsys:
  2505                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2506                              <1> 	; (Major Modification: 'core' dumping procedure in
  2507                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2508                              <1> 	;	has been changed to print 'Invalid System Call !'
  2509                              <1> 	;	message on the user's console tty.)
  2510                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2511                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2512                              <1> 	; (EAX = Function number)  
  2513                              <1> 	;
  2514 00003B86 FE05[066F0000]      <1> 	inc	byte [u.bsys]
  2515                              <1> 	;
  2516 00003B8C 8B1D[B06E0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2517 00003B92 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2518 00003B94 E860DBFFFF          <1> 	call	dwordtohex
  2519 00003B99 8915[54680000]      <1> 	mov	[bsys_msg_eip], edx
  2520 00003B9F A3[58680000]        <1> 	mov	[bsys_msg_eip+4], eax
  2521 00003BA4 A1[B86E0000]        <1> 	mov	eax, [u.r0]
  2522 00003BA9 E84BDBFFFF          <1> 	call	dwordtohex
  2523 00003BAE 8915[44680000]      <1> 	mov	[bsys_msg_eax], edx
  2524 00003BB4 A3[48680000]        <1> 	mov	[bsys_msg_eax+4], eax
  2525                              <1> 	; 24/12/2021
  2526                              <1> 	;xor	eax, eax
  2527                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2528                              <1> 	;mov	ebx, [u.fofp]
  2529                              <1> 	;mov	[ebx], eax
  2530                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2531                              <1> 	;inc	eax
  2532                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2533                              <1> 		; writei
  2534                              <1> 		; INPUTS ->
  2535                              <1> 		;    r1 - inode number
  2536                              <1> 		;    u.count - byte count to be written
  2537                              <1> 		;    u.base - points to user buffer
  2538                              <1> 		;    u.fofp - points to word with current file offset
  2539                              <1> 		; OUTPUTS ->
  2540                              <1> 		;    u.count - cleared
  2541                              <1> 		;    u.nread - accumulates total bytes passed back	
  2542                              <1> 		;
  2543                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2544                              <1> 	;call	writei
  2545                              <1> 	;;mov	eax, 1
  2546                              <1> 	;jmp	sysexit
  2547                              <1> 
  2548                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2549 00003BB9 BE[25680000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2550 00003BBE 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2551 00003BC5 8A83[176C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2552 00003BCB C605[276B0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2553 00003BD2 A2[0C6F0000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2554 00003BD7 E817260000          <1> 	call	print_cmsg
  2555                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2556 00003BDC E9F3FEFFFF          <1> 	jmp	error
  2557                              <1> 
  2558                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2559                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2560                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2561                              <1> 		; br 1f / error
  2562                              <1> 		; neg r1 / negate the i-number to open the core image file
  2563                              <1> 		       ; / for writing
  2564                              <1> 		; jsr r0,iopen / open the core image file
  2565                              <1> 		; jsr r0,itrunc / free all associated blocks
  2566                              <1> 		; br 2f
  2567                              <1> ;1:
  2568                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2569                              <1> 		; jsr r0,maknod / make an i-node
  2570                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2571                              <1> ;2:
  2572                              <1> 		; mov $core,u.base / move address core to u.base
  2573                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2574                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2575                              <1> 		; clr u.off / clear user offset
  2576                              <1> 		; jsr r0,writei / write out the core image to the user
  2577                              <1> 		; mov $user,u.base / pt. u.base to user
  2578                              <1> 		; mov $64.,u.count / u.count = 64
  2579                              <1> 		; jsr r0,writei / write out all the user parameters
  2580                              <1> 		; neg r1 / make i-number positive
  2581                              <1> 		; jsr r0,iclose / close the core image file
  2582                              <1> 		; br sysexit /
  2583                              <1> ;3:
  2584                              <1> 		; <core\0\0>
  2585                              <1> 
  2586                              <1> intract: ; / interrupt action
  2587                              <1> 	; 14/10/2015
  2588                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2589                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2590                              <1> 	;
  2591                              <1> 	; Retro UNIX 8086 v1 modification !
  2592                              <1> 	; (Process/task switching and quit routine by using
  2593                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2594                              <1> 	;
  2595                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2596                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2597                              <1> 	;		'intract' will jump to 'sysexit'.
  2598                              <1> 	;	    Intract will return to the caller 
  2599                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2600                              <1> 	; 14/10/2015
  2601 00003BE1 FB                  <1> 	sti
  2602                              <1> 	; 07/12/2013	
  2603 00003BE2 66FF05[FE6E0000]    <1> 	inc 	word [u.quit]
  2604 00003BE9 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2605 00003BEB 66FF0D[FE6E0000]    <1> 	dec	word [u.quit]
  2606                              <1> 	; 16/04/2015
  2607 00003BF2 C3                  <1> 	retn
  2608                              <1> intrct0:	
  2609 00003BF3 58                  <1> 	pop	eax ; call intract -> retn
  2610                              <1> 	;
  2611 00003BF4 31C0                <1> 	xor 	eax, eax
  2612 00003BF6 FEC0                <1> 	inc	al  ; mov ax, 1
  2613                              <1> ;;;
  2614                              <1> 	; UNIX v1 original 'intract' routine... 
  2615                              <1> 	; / interrupt action
  2616                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2617                              <1> 		; bne 1f / no, 1f
  2618                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2619                              <1> 	; 1: / now in user area
  2620                              <1> 		; mov r1,-(sp) / save r1
  2621                              <1> 		; mov u.ttyp,r1 
  2622                              <1> 			; / pointer to tty buffer in control-to r1
  2623                              <1> 		; cmpb 6(r1),$177
  2624                              <1> 			; / is the interrupt char equal to "del"
  2625                              <1> 		; beq 1f / yes, 1f
  2626                              <1> 		; clrb 6(r1) 
  2627                              <1> 		        ; / no, clear the byte 
  2628                              <1> 			; / (must be a quit character)
  2629                              <1> 		; mov (sp)+,r1 / restore r1
  2630                              <1> 		; clr u.quit / clear quit flag
  2631                              <1> 		; bis $20,2(sp) 
  2632                              <1> 		    	; / set trace for quit (sets t bit of 
  2633                              <1> 			; / ps-trace trap)
  2634                              <1> 		; rti   ;  / return from interrupt
  2635                              <1> 	; 1: / interrupt char = del
  2636                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2637                              <1> 			   ; / in the buffer
  2638                              <1> 		; mov (sp)+,r1 / restore r1
  2639                              <1> 		; cmp u.intr,$core / should control be 
  2640                              <1> 				; / transferred to loc core?
  2641                              <1> 		; blo 1f
  2642                              <1> 		; jmp *u.intr / user to do rti yes, 
  2643                              <1> 				; / transfer to loc core
  2644                              <1> 	; 1:
  2645                              <1> 		; sys 1 / exit
  2646                              <1> 
  2647                              <1> sysexit: ; <terminate process>
  2648                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2649                              <1> 	; 01/09/2015
  2650                              <1> 	; 31/08/2015
  2651                              <1> 	; 14/05/2015
  2652                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2653                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2654                              <1> 	;
  2655                              <1> 	; 'sysexit' terminates a process. First each file that
  2656                              <1> 	; the process has opened is closed by 'flose'. The process
  2657                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2658                              <1> 	; searched to find children of the dying process. If any of
  2659                              <1> 	; children are zombies (died by not waited for), they are
  2660                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2661                              <1> 	; dying process's parent. When the parent is found, it is
  2662                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2663                              <1> 	; one of these, the dying process just dies. If it is waiting
  2664                              <1> 	; for a child process to die, it notified that it doesn't 
  2665                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2666                              <1> 	; (waiting to active). It is awakened and put on runq by
  2667                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2668                              <1> 	; it will never be run again but stays around until a 'wait'
  2669                              <1> 	; is completed by it's parent process. If the parent is not
  2670                              <1> 	; found, process just dies. This means 'swap' is called with
  2671                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2672                              <1> 	; to write out the process and 'rswap' reads the new process
  2673                              <1> 	; over the one that dies..i.e., the dying process is 
  2674                              <1> 	; overwritten and destroyed.	
  2675                              <1>  	;
  2676                              <1> 	; Calling sequence:
  2677                              <1> 	;	sysexit or conditional branch.
  2678                              <1> 	; Arguments:
  2679                              <1> 	;	-	
  2680                              <1> 	; ...............................................................
  2681                              <1> 	;	
  2682                              <1> 	; Retro UNIX 8086 v1 modification: 
  2683                              <1> 	;       System call number (=1) is in EAX register.
  2684                              <1> 	;
  2685                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2686                              <1> 	;       registers depending of function details.
  2687                              <1> 	;
  2688                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2689                              <1> 	;
  2690                              <1> ; / terminate process
  2691                              <1> 	; AX = 1
  2692                              <1> 	;dec 	ax ; 0
  2693                              <1> 	; 24/12/2021
  2694 00003BF8 48                  <1> 	dec	eax ; 0
  2695                              <1> 	;dec 	ax ; 0
  2696 00003BF9 66A3[FC6E0000]      <1> 	mov	[u.intr], ax ; 0
  2697                              <1> 		; clr u.intr / clear interrupt control word
  2698                              <1> 		; clr r1 / clear r1
  2699                              <1> 	; AX = 0
  2700                              <1> sysexit_1: ; 1:
  2701                              <1> 	; AX = File descriptor
  2702                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2703                              <1> 		; / Search the whole list
  2704 00003BFF E85A0D0000          <1> 	call	fclose
  2705                              <1> 		; jsr r0,fclose / close all files the process opened
  2706                              <1> 	;; ignore error return
  2707                              <1> 		; br .+2 / ignore error return
  2708                              <1> 	;inc	ax
  2709 00003C04 FEC0                <1> 	inc	al
  2710                              <1> 		; inc r1 / increment file descriptor
  2711                              <1> 	;cmp	ax, 10
  2712 00003C06 3C0A                <1> 	cmp	al, 10
  2713                              <1> 		; cmp r1,$10. / end of u.fp list?
  2714 00003C08 72F5                <1> 	jb	short sysexit_1
  2715                              <1> 		; blt 1b / no, go back
  2716 00003C0A 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2717                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2718 00003C11 88A3[376C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2719                              <1> 		; clrb p.stat-1(r1) / free the process
  2720                              <1> 	;shl	bx, 1
  2721 00003C17 D0E3                <1> 	shl	bl, 1
  2722                              <1> 		; asl r1 / use r1 for index into the below tables
  2723 00003C19 668B8B[D66B0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2724                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2725 00003C20 668B93[F66B0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2726                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2727                              <1> 	; xor 	bx, bx ; 0
  2728 00003C27 30DB                <1> 	xor	bl, bl ; 0
  2729                              <1> 		; clr r2
  2730 00003C29 31F6                <1> 	xor	esi, esi ; 0
  2731                              <1> 		; clr r5 / initialize reg
  2732                              <1> sysexit_2: ; 1:
  2733                              <1> 	        ; / find children of this dying process, 
  2734                              <1> 		; / if they are zombies, free them
  2735                              <1> 	;add	bx, 2
  2736 00003C2B 80C302              <1> 	add	bl, 2
  2737                              <1> 		; add $2,r2 / search parent process table 
  2738                              <1> 		          ; / for dying process's name
  2739 00003C2E 66398B[F66B0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2740                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2741 00003C35 7513                <1> 	jne	short sysexit_4
  2742                              <1> 		; bne 3f / no
  2743                              <1> 	;shr	bx, 1
  2744 00003C37 D0EB                <1> 	shr	bl, 1
  2745                              <1> 		; asr r2 / yes, it is a parent
  2746 00003C39 80BB[376C0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2747                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2748                              <1> 				     ; / dying process a zombie
  2749 00003C40 7506                <1> 	jne	short sysexit_3 
  2750                              <1> 		; bne 2f / no
  2751 00003C42 88A3[376C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2752                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2753                              <1> sysexit_3: ; 2:
  2754                              <1> 	;shr	bx, 1
  2755 00003C48 D0E3                <1> 	shl	bl, 1
  2756                              <1> 		; asl r2
  2757                              <1> sysexit_4: ; 3:
  2758                              <1> 		; / search the process name table 
  2759                              <1> 		; / for the dying process's parent
  2760 00003C4A 663993[D66B0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2761                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2762 00003C51 7502                <1> 	jne	short sysexit_5
  2763                              <1> 		; bne 3f / no
  2764 00003C53 89DE                <1> 	mov	esi, ebx
  2765                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2766                              <1> 		          ; / process # x2) in r5
  2767                              <1> sysexit_5: ; 3:
  2768                              <1> 	;cmp	bx, nproc + nproc
  2769 00003C55 80FB20              <1> 	cmp	bl, nproc + nproc
  2770                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2771 00003C58 72D1                <1> 	jb	short sysexit_2
  2772                              <1> 		; blt 1b / no, go back
  2773                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2774 00003C5A 21F6                <1> 	and	esi, esi ; r5=r1
  2775 00003C5C 7431                <1> 	jz	short sysexit_6
  2776                              <1> 		; beq 2f / no parent has been found. 
  2777                              <1> 		       ; / The process just dies
  2778 00003C5E 66D1EE              <1> 	shr	si, 1
  2779                              <1> 		; asr r1 / set up index to p.stat
  2780 00003C61 8A86[376C0000]      <1> 	mov	al, [esi+p.stat-1]
  2781                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2782 00003C67 20C0                <1> 	and	al, al
  2783 00003C69 7424                <1> 	jz	short sysexit_6
  2784                              <1> 		; beq 2f / if its been freed, 2f
  2785 00003C6B 3C03                <1> 	cmp	al, 3
  2786                              <1> 		; cmp r2,$3 / is parent a zombie?
  2787 00003C6D 7420                <1> 	je	short sysexit_6
  2788                              <1> 		; beq 2f / yes, 2f
  2789                              <1> 	; BH = 0
  2790 00003C6F 8A1D[076F0000]      <1> 	mov	bl, [u.uno]
  2791                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2792 00003C75 C683[376C0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2793                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2794                              <1> 	; 05/02/2014
  2795 00003C7C 3C01                <1> 	cmp	al, 1 ; SRUN
  2796 00003C7E 740F                <1> 	je	short sysexit_6
  2797                              <1> 	;cmp	al, 2
  2798                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2799                              <1> 			  ; / this child to die
  2800                              <1> 	;jne	short sysexit_6	
  2801                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2802                              <1> 	; 05/02/2014
  2803                              <1> 	; p.stat = 2 --> waiting
  2804                              <1> 	; p.stat = 4 --> sleeping
  2805 00003C80 C686[376C0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2806                              <1> 	;dec	byte [esi+p.stat-1]
  2807                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2808 00003C87 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2809                              <1> 	; 
  2810                              <1> 	;mov	ebx, runq + 4
  2811                              <1> 		; mov $runq+4,r2 / on the runq
  2812 00003C8A E877120000          <1> 	call	putlu
  2813                              <1> 		; jsr r0, putlu
  2814                              <1> sysexit_6: ; 2:
  2815                              <1> 	; 31/08/2015
  2816                              <1> 		; / the process dies
  2817 00003C8F C605[076F0000]00    <1> 	mov	byte [u.uno], 0
  2818                              <1> 		; clrb u.uno / put zero as the process number, 
  2819                              <1> 	           ; / so "swap" will
  2820 00003C96 E89E110000          <1> 	call	swap
  2821                              <1> 		; jsr r0,swap / overwrite process with another process
  2822                              <1> hlt_sys:
  2823                              <1> 	;sti ; 18/01/2014
  2824                              <1> hlts0:
  2825 00003C9B F4                  <1> 	hlt
  2826 00003C9C EBFD                <1> 	jmp	short hlts0
  2827                              <1> 		; 0 / and thereby kill it; halt?
  2828                              <1> 
  2829                              <1> 
  2830                              <1> syswait: ; < wait for a processs to die >
  2831                              <1> 	; 09/02/2022
  2832                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2833                              <1> 	; 17/09/2015
  2834                              <1> 	; 02/09/2015
  2835                              <1> 	; 01/09/2015
  2836                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2837                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2838                              <1> 	;
  2839                              <1> 	; 'syswait' waits for a process die. 
  2840                              <1> 	; It works in following way:
  2841                              <1> 	;    1) From the parent process number, the parent's 
  2842                              <1> 	; 	process name is found. The p.ppid table of parent
  2843                              <1> 	;	names is then searched for this process name.
  2844                              <1> 	;	If a match occurs, r2 contains child's process
  2845                              <1> 	;	number. The child status is checked to see if it is
  2846                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2847                              <1> 	;	If it is, the child process is freed and it's name
  2848                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2849                              <1> 	;	If the child is not a zombie, nothing happens and
  2850                              <1> 	;	the search goes on through the p.ppid table until
  2851                              <1> 	;	all processes are checked or a zombie is found.
  2852                              <1> 	;    2) If no zombies are found, a check is made to see if
  2853                              <1> 	;	there are any children at all. If there are none,
  2854                              <1> 	;	an error return is made. If there are, the parent's
  2855                              <1> 	;	status is set to 2 (waiting for child to die),
  2856                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2857                              <1> 	;	is made to wait on the next process.
  2858                              <1> 	;
  2859                              <1> 	; Calling sequence:
  2860                              <1> 	;	?
  2861                              <1> 	; Arguments:
  2862                              <1> 	;	-
  2863                              <1> 	; Inputs: - 
  2864                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2865                              <1> 	; ...............................................................
  2866                              <1> 	;				
  2867                              <1> 	
  2868                              <1> ; / wait for a process to die
  2869                              <1> 
  2870                              <1> syswait_0:
  2871 00003C9E 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2872                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2873 00003CA5 D0E3                <1> 	shl	bl, 1
  2874                              <1> 	;shl	bx, 1
  2875                              <1> 		; asl r1 / x2 to get index into p.pid table
  2876 00003CA7 668B83[D66B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2877                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2878 00003CAE 31F6                <1> 	xor	esi, esi
  2879                              <1> 		; clr r2
  2880 00003CB0 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2881                              <1> 	;xor 	cl, cl
  2882                              <1> 		; clr r3 / initialize reg 3
  2883                              <1> syswait_1: ; 1:
  2884                              <1> 	; 09/02/2022
  2885 00003CB2 46                  <1> 	inc	esi
  2886 00003CB3 46                  <1> 	inc	esi
  2887                              <1> 	;add	si, 2
  2888                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2889                              <1> 			  ; / search table of parent processes 
  2890                              <1> 			  ; / for this process name
  2891 00003CB4 663B86[F66B0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2892                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2893                              <1> 			            ; / process number
  2894 00003CBB 7531                <1> 	jne	short syswait_3
  2895                              <1> 		;bne 3f / branch if no match of parent process name
  2896                              <1> 	;inc	cx
  2897 00003CBD FEC1                <1> 	inc	cl
  2898                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2899                              <1> 	; 09/02/2022
  2900 00003CBF D1EE                <1> 	shr	esi, 1
  2901                              <1> 	;shr	si, 1
  2902                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2903                              <1> 	; The possible states ('p.stat' values) of a process are:
  2904                              <1> 	;	0 = free or unused
  2905                              <1> 	;	1 = active
  2906                              <1> 	;	2 = waiting for a child process to die
  2907                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2908 00003CC1 80BE[376C0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2909                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2910 00003CC8 7522                <1> 	jne	short syswait_2
  2911                              <1> 		; bne 2f / no, skip it
  2912 00003CCA 88BE[376C0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2913                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2914                              <1> 	; 09/02/2022
  2915 00003CD0 D1E6                <1> 	shl	esi, 1
  2916                              <1> 	;shl	si, 1
  2917                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2918 00003CD2 0FB786[D66B0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2919 00003CD9 A3[B86E0000]        <1> 	mov	[u.r0], eax
  2920                              <1> 		; mov p.pid-2(r2),*u.r0 
  2921                              <1> 			      ; / put childs process name in (u.r0)
  2922                              <1> 	;
  2923                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2924                              <1> 	;
  2925                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2926                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2927                              <1> 	; system call loop from the application/program if it calls
  2928                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2929                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2930                              <1> 	;
  2931                              <1> 	; Note: syswait will return with error if there is not a
  2932                              <1> 	;       zombie or running process to wait.	
  2933                              <1> 	;
  2934                              <1> 	;sub	ax, ax
  2935                              <1> 	; 08/01/2022
  2936 00003CDE 29C0                <1> 	sub	eax, eax
  2937 00003CE0 668986[F66B0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2938 00003CE7 E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2939                              <1> 	;
  2940                              <1> 	;jmp	sysret
  2941                              <1> 		; br sysret1 / return cause child is dead
  2942                              <1> syswait_2: ; 2:
  2943                              <1> 	; 09/02/2022
  2944 00003CEC D1E6                <1> 	shl	esi, 1
  2945                              <1> 	;shl	si, 1
  2946                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2947                              <1> syswait_3: ; 3:
  2948 00003CEE 6683FE20            <1> 	cmp	si, nproc+nproc
  2949                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2950 00003CF2 72BE                <1> 	jb	short syswait_1
  2951                              <1> 		; blt 1b / no, continue search
  2952                              <1> 	;and	cx, cx
  2953 00003CF4 20C9                <1> 	and	cl, cl
  2954                              <1> 		; tst r3 / one gets here if there are no children 
  2955                              <1> 		       ; / or children that are still active
  2956                              <1> 	; 30/10/2013
  2957 00003CF6 7515                <1> 	jnz	short syswait_4
  2958                              <1> 	;jz	error
  2959                              <1> 		; beq error1 / there are no children, error
  2960 00003CF8 890D[B86E0000]      <1> 	mov	[u.r0], ecx ; 0
  2961                              <1> 	; 09/02/2022
  2962 00003CFE C705[0D6F0000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2962 00003D06 0000                <1>
  2963                              <1> 			; miscellaneous/other errors
  2964 00003D08 E9C7FDFFFF          <1> 	jmp	error
  2965                              <1> syswait_4:
  2966 00003D0D 8A1D[076F0000]      <1> 	mov	bl, [u.uno]
  2967                              <1> 		; movb u.uno,r1 / there are children so put 
  2968                              <1> 			      ; / parent process number in r1
  2969 00003D13 FE83[376C0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2970                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2971                              <1> 				  ; / other children to die
  2972                              <1> 	; 04/11/2013
  2973 00003D19 E81B110000          <1> 	call	swap
  2974                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2975 00003D1E E97BFFFFFF          <1> 	jmp	syswait_0
  2976                              <1> 		; br syswait / wait on next process
  2977                              <1> 
  2978                              <1> sysfork: ; < create a new process >
  2979                              <1> 	; 26/02/2022
  2980                              <1> 	; 25/02/2022
  2981                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2982                              <1> 	; 18/09/2015
  2983                              <1> 	; 04/09/2015
  2984                              <1> 	; 02/09/2015
  2985                              <1> 	; 01/09/2015
  2986                              <1> 	; 28/08/2015
  2987                              <1> 	; 14/05/2015
  2988                              <1> 	; 10/05/2015
  2989                              <1> 	; 09/05/2015
  2990                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2991                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2992                              <1> 	;
  2993                              <1> 	; 'sysfork' creates a new process. This process is referred
  2994                              <1> 	; to as the child process. This new process core image is
  2995                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2996                              <1> 	; distinction is the return location and the fact that (u.r0)
  2997                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2998                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2999                              <1> 	; 'sysfork' works in the following manner: 	
  3000                              <1> 	;    1) The process status table (p.stat) is searched to find
  3001                              <1> 	;	a process number that is unused. If none are found
  3002                              <1> 	;	an error occurs.
  3003                              <1> 	;    2) when one is found, it becomes the child process number
  3004                              <1> 	;	and it's status (p.stat) is set to active.
  3005                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3006                              <1> 	;	character in that tty buffer is cleared.
  3007                              <1> 	;    4) The child process is put on the lowest priority run 
  3008                              <1> 	;	queue via 'putlu'.
  3009                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3010                              <1> 	;	it is a unique number) and is put in the child's unique
  3011                              <1> 	;	identifier; process id (p.pid).
  3012                              <1> 	;    6) The process name of the parent is then obtained and
  3013                              <1> 	;	placed in the unique identifier of the parent process
  3014                              <1> 	;	name is then put in 'u.r0'.	
  3015                              <1> 	;    7) The child process is then written out on disk by
  3016                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3017                              <1> 	;	and the child is born. (The child process is written 
  3018                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3019                              <1> 	;	number.)
  3020                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3021                              <1> 	;    9) The child process name is put in 'u.r0'.
  3022                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3023                              <1> 	;	create the return address for the parent process.
  3024                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3025                              <1> 	;	the parent has opened. For each file the parent has
  3026                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3027                              <1> 	;	to indicate that the child process also has opened
  3028                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3029                              <1> 	;
  3030                              <1> 	; Calling sequence:
  3031                              <1> 	;	from shell ?
  3032                              <1> 	; Arguments:
  3033                              <1> 	;	-
  3034                              <1> 	; Inputs: -
  3035                              <1> 	; Outputs: *u.r0 - child process name
  3036                              <1> 	; ...............................................................
  3037                              <1> 	;	
  3038                              <1> 	; Retro UNIX 8086 v1 modification: 
  3039                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3040                              <1> 	;	= process id of child a parent process returns
  3041                              <1> 	;	= process id of parent when a child process returns
  3042                              <1> 	;
  3043                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3044                              <1> 	;	in following manner: (with an example: c library, fork)
  3045                              <1> 	;	
  3046                              <1> 	;	1:
  3047                              <1> 	;		sys	fork
  3048                              <1> 	;			br 1f  / child process returns here
  3049                              <1> 	;		bes	2f     / parent process returns here
  3050                              <1> 	;		/ pid of new process in r0
  3051                              <1> 	;		rts	pc
  3052                              <1> 	;	2: / parent process condionally branches here
  3053                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3054                              <1> 	;		rts	pc
  3055                              <1> 	;
  3056                              <1> 	;	1: / child process brances here
  3057                              <1> 	;		clr	r0   / pid = 0 in child process
  3058                              <1> 	;		rts	pc
  3059                              <1> 	;
  3060                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3061                              <1> 	;		// pid = fork();
  3062                              <1> 	;		//
  3063                              <1> 	;		// pid == 0 in child process; 
  3064                              <1> 	;		// pid == -1 means error return
  3065                              <1> 	;		// in child, 
  3066                              <1> 	;		//	parents id is in par_uid if needed
  3067                              <1> 	;		
  3068                              <1> 	;		_fork:
  3069                              <1> 	;			mov	$.fork,eax
  3070                              <1> 	;			int	$0x30
  3071                              <1> 	;			jmp	1f
  3072                              <1> 	;			jnc	2f
  3073                              <1> 	;			jmp	cerror
  3074                              <1> 	;		1:
  3075                              <1> 	;			mov	eax,_par_uid
  3076                              <1> 	;			xor	eax,eax
  3077                              <1> 	;		2:
  3078                              <1> 	;			ret
  3079                              <1> 	;
  3080                              <1> 	;	In Retro UNIX 8086 v1,
  3081                              <1> 	;	'sysfork' returns in following manner:
  3082                              <1> 	;	
  3083                              <1> 	;		mov	ax, sys_fork
  3084                              <1> 	;		mov	bx, offset @f ; routine for child
  3085                              <1> 	;		int	20h
  3086                              <1> 	;		jc	error
  3087                              <1> 	;		
  3088                              <1> 	;	; Routine for parent process here (just after 'jc')
  3089                              <1> 	;		mov	word ptr [pid_of_child], ax
  3090                              <1> 	;		jmp	next_routine_for_parent	
  3091                              <1> 	;
  3092                              <1> 	;	@@: ; routine for child process here				
  3093                              <1> 	;		....	
  3094                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3095                              <1> 	;	       for child process by using BX input.
  3096                              <1> 	;	      (at first, parent process will return then 
  3097                              <1> 	;	      child process will return -after swapped in-
  3098                              <1> 	;	      'syswait' is needed in parent process
  3099                              <1> 	;	      if return from child process will be waited for.)
  3100                              <1> 	;	  				
  3101                              <1> 	
  3102                              <1> ; / create a new process
  3103                              <1> 	; EBX = return address for child process 
  3104                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3105 00003D23 31F6                <1> 	xor 	esi, esi
  3106                              <1> 		; clr r1
  3107                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3108 00003D25 46                  <1> 	inc	esi
  3109                              <1> 		; inc r1
  3110 00003D26 80BE[376C0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3111                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3112 00003D2D 760B                <1> 	jna	short sysfork_2	
  3113                              <1> 		; beq 1f / it's unused so branch
  3114 00003D2F 6683FE10            <1> 	cmp	si, nproc
  3115                              <1> 		; cmp r1,$nproc / all processes checked
  3116 00003D33 72F0                <1> 	jb	short sysfork_1
  3117                              <1> 		; blt 1b / no, branch back
  3118                              <1> 	;
  3119                              <1> 	; Retro UNIX 8086 v1. modification:
  3120                              <1> 	;	Parent process returns from 'sysfork' to address 
  3121                              <1> 	;	which is just after 'sysfork' system call in parent
  3122                              <1> 	;	process. Child process returns to address which is put
  3123                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3124                              <1> 	;
  3125                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3126                              <1> 		             ; / to old process return
  3127                              <1> 		; br error1 / no room for a new process
  3128                              <1> sysfork_0:
  3129 00003D35 E99AFDFFFF          <1> 	jmp	error
  3130                              <1> sysfork_2: ; 1:
  3131 00003D3A E879F0FFFF          <1> 	call	allocate_page
  3132                              <1> 	;jc	error
  3133                              <1> 	; 08/01/2022
  3134 00003D3F 72F4                <1> 	jc	short sysfork_0
  3135                              <1> 
  3136 00003D41 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3137                              <1> 	; Retro UNIX 386 v1 modification!
  3138 00003D42 E86AF2FFFF          <1> 	call	duplicate_page_dir
  3139                              <1> 		; EAX = New page directory 
  3140 00003D47 7308                <1> 	jnc	short sysfork_3
  3141 00003D49 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3142 00003D4A E831F2FFFF          <1> 	call 	deallocate_page
  3143                              <1> 	;jmp	error
  3144                              <1> 	; 08/01/2022
  3145 00003D4F EBE4                <1> 	jmp	short sysfork_0 ; error
  3146                              <1> sysfork_3:
  3147                              <1> 	; Retro UNIX 386 v1 modification !
  3148 00003D51 56                  <1> 	push	esi
  3149 00003D52 E859110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3150                              <1> 		      ; and interrupt return components (for IRET)
  3151 00003D57 8705[116F0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3152 00003D5D A3[156F0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3153 00003D62 5E                  <1> 	pop	esi
  3154 00003D63 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3155                              <1> 		; [u.usp] = esp
  3156 00003D64 89F7                <1> 	mov	edi, esi
  3157                              <1> 	;shl	di, 2
  3158                              <1> 	; 08/01/2022
  3159 00003D66 C1E702              <1> 	shl	edi, 2
  3160 00003D69 8987[446C0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3161 00003D6F A3[086F0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3162                              <1> 	; 28/08/2015
  3163 00003D74 0FB605[076F0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3164                              <1> 		; movb u.uno,-(sp) / save parent process number
  3165 00003D7B 89C7                <1> 	mov	edi, eax
  3166 00003D7D 50                  <1>         push	eax ; ** 
  3167 00003D7E 8A87[176C0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3168                              <1> 		; 18/09/2015
  3169 00003D84 8886[176C0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3170                              <1> 	; 26/02/2022 (p.waitc is not used)
  3171                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3172                              <1> 	; 25/02/2022 (BugFix)
  3173                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3174                              <1> 	;			   ; ah - reset child's wait channel	
  3175 00003D8A 89F0                <1> 	mov	eax, esi
  3176 00003D8C A2[076F0000]        <1> 	mov	[u.uno], al ; child process number
  3177                              <1> 		;movb r1,u.uno / set child process number to r1
  3178 00003D91 FE86[376C0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3179                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3180                              <1> 				; / process to active status
  3181                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3182                              <1> 			      ; / control tty buffer in r2
  3183                              <1>                 ; beq 2f / branch, if no such tty assigned
  3184                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3185                              <1> 	; 2:
  3186 00003D97 53                  <1> 	push	ebx  ; * return address for the child process
  3187                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3188                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3189                              <1> 		; mov $runq+4,r2
  3190 00003D98 E869110000          <1> 	call	putlu 
  3191                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3192                              <1> 			   ; / run queue
  3193                              <1> 	; 08/01/2022
  3194 00003D9D D1E6                <1> 	shl	esi, 1
  3195                              <1> 	;shl	si, 1
  3196                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3197                              <1> 		       ; / into p.pid table
  3198 00003D9F 66FF05[A66E0000]    <1> 	inc	word [mpid]
  3199                              <1> 		; inc mpid / increment m.pid; get a new process name
  3200 00003DA6 66A1[A66E0000]      <1> 	mov	ax, [mpid]
  3201 00003DAC 668986[D66B0000]    <1> 	mov	[esi+p.pid-2], ax
  3202                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3203                              <1> 				    ; / in child process' name slot
  3204 00003DB3 5A                  <1> 	pop	edx  ; * return address for the child process
  3205                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3206 00003DB4 5B                  <1>   	pop	ebx  ; **
  3207                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3208                              <1> 		; movb (sp),r2 / put parent process number in r2
  3209                              <1> 	; 08/01/2022
  3210 00003DB5 D1E3                <1> 	shl	ebx, 1
  3211                              <1> 	;shl 	bx, 1
  3212                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3213                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3214 00003DB7 668B83[D66B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3215                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3216                              <1> 				   ; / process
  3217 00003DBE 668986[F66B0000]    <1> 	mov	[esi+p.ppid-2], ax
  3218                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3219                              <1> 			  ; / in parent process slot for child
  3220 00003DC5 A3[B86E0000]        <1> 	mov	[u.r0], eax	
  3221                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3222                              <1> 			     ; / at location where r0 was saved
  3223 00003DCA 8B2D[B06E0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3224 00003DD0 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3225                              <1> 			   ; * return address for the child process
  3226                              <1> 		; mov $sysret1,-(sp) /
  3227                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3228                              <1> 			      ; / user is swapped out
  3229                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3230                              <1> 	; 04/09/2015 - 01/09/2015
  3231                              <1> 	; [u.usp] = esp
  3232 00003DD3 68[F43A0000]        <1> 	push	sysret ; ***
  3233 00003DD8 8925[B46E0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3234                              <1> 			     ; (for child process)	
  3235 00003DDE 31C0                <1> 	xor 	eax, eax
  3236 00003DE0 66A3[E86E0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3237                              <1> 	;
  3238 00003DE6 E8C5100000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3239                              <1> 		;jsr r0,wswap / put child process out on drum
  3240                              <1> 		;jsr r0,unpack / unpack user stack
  3241                              <1> 		;mov u.usp,sp / restore user stack pointer
  3242                              <1> 		; tst (sp)+ / bump stack pointer
  3243                              <1> 	; Retro UNIX 386 v1 modification !
  3244 00003DEB 58                  <1> 	pop	eax ; ***
  3245                              <1> 	; 08/01/2022
  3246 00003DEC D1E3                <1> 	shl	ebx, 1
  3247                              <1> 	;shl 	bx, 1
  3248 00003DEE 8B83[446C0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3249 00003DF4 E8E0100000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3250                              <1> 		      ; registers and return address (for IRET)
  3251                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3252 00003DF9 0FB705[A66E0000]    <1>         movzx   eax, word [mpid]
  3253 00003E00 A3[B86E0000]        <1> 	mov	[u.r0], eax
  3254                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3255                              <1> 			       ; / where r0 was saved
  3256                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3257                              <1> 			          ; / process return
  3258                              <1> 	;xor	ebx, ebx
  3259 00003E05 31F6                <1> 	xor     esi, esi
  3260                              <1> 		;clr r1
  3261                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3262                              <1> 	      ; / opened by the parent process
  3263                              <1> 	; 01/09/2015
  3264                              <1> 	;xor	bh, bh
  3265                              <1> 	;mov 	bl, [esi+u.fp]
  3266 00003E07 8A86[BE6E0000]      <1> 	mov 	al, [esi+u.fp]
  3267                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3268                              <1>         ;or	bl, bl
  3269 00003E0D 08C0                <1> 	or	al, al
  3270 00003E0F 740C                <1> 	jz	short sysfork_5	
  3271                              <1> 		; beq 2f / file has not been opened by parent, 
  3272                              <1> 		       ; / so branch
  3273 00003E11 B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3274 00003E13 F6E4                <1> 	mul	ah
  3275                              <1> 	;;movzx	ebx, ax
  3276                              <1> 	;mov	bx, ax
  3277 00003E15 89C3                <1> 	mov	ebx, eax ; 08/01/2022
  3278                              <1> 	;shl	bx, 3
  3279                              <1> 		; asl r2 / multiply by 8
  3280                              <1>        		; asl r2 / to get index into fsp table
  3281                              <1>        		; asl r2
  3282 00003E17 FE83[866C0000]      <1>   	inc     byte [ebx+fsp-2]
  3283                              <1> 		; incb fsp-2(r2) / increment number of processes
  3284                              <1> 			     ; / using file, because child will now be
  3285                              <1> 			     ; / using this file
  3286                              <1> sysfork_5: ; 2:
  3287 00003E1D 46                  <1>         inc     esi
  3288                              <1> 		; inc r1 / get next open file
  3289 00003E1E 6683FE0A            <1>         cmp     si, 10
  3290                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3291                              <1> 			  ; / can be opened
  3292 00003E22 72E3                <1> 	jb	short sysfork_4	
  3293                              <1> 		; blt 1b / check next entry
  3294 00003E24 E9CBFCFFFF          <1> 	jmp	sysret
  3295                              <1> 		; br sysret1
  3296                              <1> 
  3297                              <1> sysread: ; < read from file >
  3298                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3299                              <1> 	; 13/05/2015
  3300                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3301                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3302                              <1> 	;
  3303                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3304                              <1> 	; characters to be read. If finds the file from the file
  3305                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3306                              <1> 	; is returned from a successful open call (sysopen).
  3307                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3308                              <1> 	; is read into core via 'readi'.
  3309                              <1> 	;
  3310                              <1> 	; Calling sequence:
  3311                              <1> 	;	sysread; buffer; nchars
  3312                              <1> 	; Arguments:
  3313                              <1> 	;	buffer - location of contiguous bytes where 
  3314                              <1> 	;		 input will be placed.
  3315                              <1> 	;	nchars - number of bytes or characters to be read.
  3316                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3317                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3318                              <1> 	; ...............................................................
  3319                              <1> 	;				
  3320                              <1> 	; Retro UNIX 8086 v1 modification: 
  3321                              <1> 	;       'sysread' system call has three arguments; so,
  3322                              <1> 	;	* 1st argument, file descriptor is in BX register
  3323                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3324                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3325                              <1> 	;
  3326                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3327                              <1> 	;	to the user with number of bytes read. 
  3328                              <1> 	;
  3329 00003E29 E840000000          <1> 	call	rw1
  3330                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3331                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3332                              <1>        	; 24/12/2021
  3333 00003E2E 7239                <1> 	jc	short sysread_err
  3334 00003E30 F6C480              <1> 	test	ah, 80h
  3335                              <1> 		; tst r1 / negative i-number?
  3336 00003E33 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3337                              <1> 	;jnz	error
  3338                              <1> 		; ble error1 / yes, error 1 to read
  3339                              <1> 			   ; / it should be positive
  3340 00003E35 E831150000          <1> 	call	readi
  3341                              <1> 		; jsr r0,readi / read data into core
  3342 00003E3A EB14                <1> 	jmp	short rw0
  3343                              <1> 		; br 1f
  3344                              <1> syswrite: ; < write to file >
  3345                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3346                              <1> 	; 13/05/2015
  3347                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3348                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3349                              <1> 	;
  3350                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3351                              <1> 	; and the number of characters to write. If finds the file
  3352                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3353                              <1> 	; descriptor is returned from a successful open or create call
  3354                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3355                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3356                              <1> 	;
  3357                              <1> 	; Calling sequence:
  3358                              <1> 	;	syswrite; buffer; nchars
  3359                              <1> 	; Arguments:
  3360                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3361                              <1> 	;	nchars - number of characters to be written.
  3362                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3363                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3364                              <1> 	; ...............................................................
  3365                              <1> 	;				
  3366                              <1> 	; Retro UNIX 8086 v1 modification: 
  3367                              <1> 	;       'syswrite' system call has three arguments; so,
  3368                              <1> 	;	* 1st argument, file descriptor is in BX register
  3369                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3370                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3371                              <1> 	;
  3372                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3373                              <1> 	;	to the user with number of bytes written. 
  3374                              <1> 	;
  3375 00003E3C E82D000000          <1> 	call	rw1
  3376                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3377                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3378                              <1>        	; 24/12/2021
  3379 00003E41 7226                <1> 	jc	short syswrite_err
  3380 00003E43 F6C480              <1>         test	ah, 80h
  3381                              <1> 		; tst r1 / positive i-number ?
  3382 00003E46 7417                <1>         jz	short rw3 ; 13/05/2015
  3383                              <1> 	;jz	error
  3384                              <1> 		; bge error1 / yes, error 1 
  3385                              <1> 			   ; / negative i-number means write
  3386 00003E48 66F7D8              <1>         neg	ax
  3387                              <1> 		; neg r1 / make it positive
  3388 00003E4B E809170000          <1> 	call	writei
  3389                              <1>         	; jsr r0,writei / write data
  3390                              <1> rw0: ; 1:
  3391 00003E50 A1[E06E0000]        <1>         mov	eax, [u.nread]
  3392 00003E55 A3[B86E0000]        <1> 	mov	[u.r0], eax
  3393                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3394                              <1> 				  ; / into (u.r0)
  3395 00003E5A E995FCFFFF          <1> 	jmp	sysret
  3396                              <1>         	; br sysret1
  3397                              <1> 
  3398                              <1> rw3: 
  3399                              <1> 	; 13/05/2015
  3400 00003E5F C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3400 00003E67 0000                <1>
  3401                              <1> 	;stc
  3402                              <1> 	;retn
  3403                              <1> 	; 24/12/2021 (BugFix)
  3404                              <1> sysread_err:
  3405                              <1> syswrite_err:
  3406 00003E69 E966FCFFFF          <1> 	jmp	error
  3407                              <1> 
  3408                              <1> rw1:	
  3409                              <1> 	; 14/05/2015
  3410                              <1> 	; 13/05/2015
  3411                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3412                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3413                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3414                              <1> 	;
  3415                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3416                              <1> 				;(in the user's virtual memory space)
  3417                              <1> 	;mov	[u.count], edx 
  3418                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3419                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3420                              <1> 	;;mov	eax, ebx ; file descriptor
  3421                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3422                              <1> 		             ; / (index to u.fp table) in r1
  3423                              <1> 	; 13/05/2015
  3424 00003E6E C705[B86E0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3424 00003E76 0000                <1>
  3425                              <1> 	;
  3426                              <1> 	;; call	getf
  3427                              <1>         ; eBX = File descriptor
  3428 00003E78 E8240B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3429                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3430                              <1> 	; AX = I-number of the file ; negative i-number means write
  3431                              <1> 	; 13/05/2015
  3432 00003E7D 6683F801            <1> 	cmp 	ax, 1
  3433 00003E81 7217                <1> 	jb	short rw2
  3434                              <1> 	;
  3435 00003E83 890D[D86E0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3436                              <1> 				;(in the user's virtual memory space)
  3437 00003E89 8915[DC6E0000]      <1> 	mov	[u.count], edx 
  3438                              <1> 	; 14/05/2015
  3439 00003E8F C705[0D6F0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3439 00003E97 0000                <1>
  3440 00003E99 C3                  <1> 	retn
  3441                              <1>         	; rts r0
  3442                              <1> rw2:
  3443                              <1> 	; 13/05/2015
  3444 00003E9A C705[0D6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3444 00003EA2 0000                <1>
  3445 00003EA4 C3                  <1> 	retn
  3446                              <1> 
  3447                              <1> sysopen: ;<open file>
  3448                              <1> 	; 09/01/2022
  3449                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3450                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3451                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3452                              <1> 	;
  3453                              <1> 	; 'sysopen' opens a file in following manner:
  3454                              <1> 	;    1) The second argument in a sysopen says whether to
  3455                              <1> 	;	open the file ro read (0) or write (>0).
  3456                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3457                              <1> 	;    3) The file is opened by 'iopen'.
  3458                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3459                              <1> 	;	and the user's open file list - u.fp.
  3460                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3461                              <1> 	;	b) An entry for the file is created in the fsp table.
  3462                              <1> 	;	c) The number of this entry is put on u.fp list.
  3463                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3464                              <1> 	;	   to by u.r0.
  3465                              <1> 	;
  3466                              <1> 	; Calling sequence:
  3467                              <1> 	;	sysopen; name; mode
  3468                              <1> 	; Arguments:
  3469                              <1> 	;	name - file name or path name
  3470                              <1> 	;	mode - 0 to open for reading
  3471                              <1> 	;	       1 to open for writing
  3472                              <1> 	; Inputs: (arguments)
  3473                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3474                              <1> 	;		  is put into r0's location on the stack.	
  3475                              <1> 	; ...............................................................
  3476                              <1> 	;				
  3477                              <1> 	; Retro UNIX 8086 v1 modification: 
  3478                              <1> 	;       'sysopen' system call has two arguments; so,
  3479                              <1> 	;	* 1st argument, name is pointed to by BX register
  3480                              <1> 	;	* 2nd argument, mode is in CX register
  3481                              <1> 	;
  3482                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3483                              <1> 	;	to the user with the file descriptor/number 
  3484                              <1> 	;	(index to u.fp list).
  3485                              <1> 	;
  3486                              <1> 	;call	arg2
  3487                              <1> 	; * name - 'u.namep' points to address of file/path name
  3488                              <1> 	;          in the user's program segment ('u.segmnt')
  3489                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3490                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3491                              <1> 	;          which is on top of stack.
  3492                              <1> 	;
  3493                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3494                              <1> 	;
  3495                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3496                              <1> 
  3497 00003EA5 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  3498                              <1> 	; 24/12/2021 (cx -> ecx)
  3499 00003EAB 51                  <1> 	push	ecx ; * 
  3500 00003EAC E8210B0000          <1> 	call	namei
  3501                              <1> 		; jsr r0,namei / i-number of file in r1
  3502                              <1>      	;and	ax, ax
  3503                              <1> 	;jz	error ; File not found
  3504 00003EB1 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3505                              <1> 	;jc	error ; 27/05/2013
  3506                              <1> 		; br  error2 / file not found
  3507                              <1>    	; 24/12/2021
  3508                              <1> 	;pop	edx ; * ; mode
  3509                              <1> 	;push	edx ; *
  3510 00003EB3 8B1424              <1> 	mov	edx, [esp] ; *
  3511                              <1> 	; edx = open mode (0 or 1)
  3512                              <1> 	;or	dx, dx
  3513 00003EB6 08D2                <1> 	or	dl, dl
  3514                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3515                              <1> 		         ; / 0 means, open for read)
  3516 00003EB8 7403                <1> 	jz	short sysopen_0
  3517                              <1> 		; beq 1f / yes, leave i-number positive
  3518                              <1> syscreat_0: ; 27/12/2015
  3519 00003EBA 66F7D8              <1> 	neg	ax
  3520                              <1>         	; neg r1 / open for writing so make i-number negative
  3521                              <1> sysopen_0: ;1:
  3522 00003EBD E8591A0000          <1> 	call	iopen
  3523                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3524 00003EC2 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3525                              <1> 	;and	dx, dx
  3526 00003EC3 20D2                <1> 	and	dl, dl
  3527                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3528 00003EC5 7403                <1> 	jz	short sysopen_2
  3529                              <1>         	; beq op1 / is open for read op1
  3530                              <1> sysopen_1: ;op0:
  3531 00003EC7 66F7D8              <1> 	neg	ax
  3532                              <1>         	; neg r1 
  3533                              <1> 	;; NOTE: iopen always make i-number positive.
  3534                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3535                              <1> sysopen_2: ;op1:
  3536 00003ECA 31F6                <1>         xor     esi, esi
  3537                              <1>         	; clr r2 / clear registers
  3538 00003ECC 31DB                <1>         xor     ebx, ebx
  3539                              <1> 		; clr r3
  3540                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3541 00003ECE 389E[BE6E0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3542                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3543 00003ED4 7625                <1>         jna      short sysopen_4
  3544                              <1> 		; beq 1f / if byte in list is 0 branch
  3545 00003ED6 46                  <1>         inc     esi
  3546                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3547 00003ED7 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3548                              <1> 		; cmp r2,$10. / reached end of list?
  3549 00003EDB 72F1                <1> 	jb	short sysopen_3
  3550                              <1> 		; blt 1b / no, go back
  3551                              <1> toomanyf:
  3552                              <1> 	; 14/05/2015
  3553 00003EDD C705[0D6F0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3553 00003EE5 0000                <1>
  3554 00003EE7 E9E8FBFFFF          <1> 	jmp	error
  3555                              <1>         	; br error2 / yes, error (no files open)
  3556                              <1> fnotfound: 
  3557                              <1> 	; 14/05/2015
  3558 00003EEC C705[0D6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3558 00003EF4 0000                <1>
  3559 00003EF6 E9D9FBFFFF          <1> 	jmp	error
  3560                              <1> 
  3561                              <1> sysopen_4: ; 1:
  3562 00003EFB 6683BB[886C0000]00  <1>         cmp     word [ebx+fsp], 0
  3563                              <1> 		; tst fsp(r3) / scan fsp entries
  3564 00003F03 760D                <1>         jna     short sysopen_5
  3565                              <1> 		; beq 1f / if 0 branch
  3566                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3567 00003F05 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3568                              <1> 		; add $8.,r3 / add 8 to r3 
  3569                              <1> 			; / to bump it to next entry mfsp table
  3570 00003F09 6681FBF401          <1>         cmp     bx, nfiles*10
  3571                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3572 00003F0E 72EB                <1> 	jb	short sysopen_4
  3573                              <1>        		; blt 1b / no, back
  3574                              <1> 	;jmp	error
  3575                              <1>         ;	; br error2 / yes, error
  3576                              <1> 	; 24/12/2021
  3577 00003F10 EBCB                <1> 	jmp	short toomanyf
  3578                              <1> 
  3579                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3580 00003F12 668983[886C0000]    <1>         mov     [ebx+fsp], ax
  3581                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3582                              <1> 			; / into next available entry in fsp table,
  3583                              <1> 	; 09/01/2022
  3584                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3585                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3586                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3587                              <1> 	;xor	edi, edi
  3588                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3589                              <1> 	;	; clr fsp+4(r3)
  3590                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3591                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3592 00003F19 31C0                <1> 	xor	eax, eax
  3593 00003F1B 8983[8C6C0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3594 00003F21 668983[906C0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3595                              <1> 
  3596 00003F28 A0[9F6E0000]        <1> 	mov	al, [cdev]
  3597 00003F2D 668983[8A6C0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3598                              <1> 
  3599 00003F34 89D8                <1>   	mov	eax, ebx
  3600 00003F36 B30A                <1> 	mov	bl, 10
  3601 00003F38 F6F3                <1> 	div	bl 
  3602                              <1> 		; asr r3
  3603                              <1> 		; asr r3 / divide by 8 
  3604                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3605 00003F3A FEC0                <1> 	inc	al
  3606                              <1>         	; inc r3 / add 1 to get fsp entry number
  3607 00003F3C 8886[BE6E0000]      <1>         mov     [esi+u.fp], al
  3608                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3609                              <1> 			; / next available slot in u.fp list
  3610 00003F42 8935[B86E0000]      <1>         mov     [u.r0], esi
  3611                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3612                              <1> 			     ; / into r0 loc on stack
  3613 00003F48 E9A7FBFFFF          <1>         jmp	sysret
  3614                              <1> 		; br sysret2
  3615                              <1> 
  3616                              <1> 	;
  3617                              <1> 	; 'fsp' table (10 bytes/entry)
  3618                              <1> 	; bit 15				   bit 0
  3619                              <1> 	; ---|-------------------------------------------
  3620                              <1> 	; r/w|		i-number of open file
  3621                              <1> 	; ---|-------------------------------------------
  3622                              <1> 	;		   device number
  3623                              <1> 	; -----------------------------------------------
  3624                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3625                              <1> 	; -----------------------------------------------
  3626                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3627                              <1> 	; ----------------------|------------------------
  3628                              <1> 	;  flag that says file 	| number of processes
  3629                              <1> 	;   has been deleted	| that have file open 
  3630                              <1> 	; ----------------------|------------------------
  3631                              <1> 	;
  3632                              <1> 
  3633                              <1> syscreat: ; < create file >
  3634                              <1> 	; 24/12/2021
  3635                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3636                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3637                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3638                              <1> 	;
  3639                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3640                              <1> 	; u.namep points to name of the file and mode is put
  3641                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3642                              <1> 	; If the file aready exists, it's mode and owner remain 
  3643                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3644                              <1> 	; did not exist, an i-node is created with the new mode via
  3645                              <1> 	; 'maknod' whether or not the file already existed, it is
  3646                              <1> 	; open for writing. The fsp table is then searched for a free
  3647                              <1> 	; entry. When a free entry is found, proper data is placed
  3648                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3649                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3650                              <1> 	; is put in the user's r0. 			
  3651                              <1> 	;
  3652                              <1> 	; Calling sequence:
  3653                              <1> 	;	syscreate; name; mode
  3654                              <1> 	; Arguments:
  3655                              <1> 	;	name - name of the file to be created
  3656                              <1> 	;	mode - mode of the file to be created
  3657                              <1> 	; Inputs: (arguments)
  3658                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3659                              <1> 	;		   (the file descriptor of new file)
  3660                              <1> 	; ...............................................................
  3661                              <1> 	;				
  3662                              <1> 	; Retro UNIX 8086 v1 modification: 
  3663                              <1> 	;       'syscreate' system call has two arguments; so,
  3664                              <1> 	;	* 1st argument, name is pointed to by BX register
  3665                              <1> 	;	* 2nd argument, mode is in CX register
  3666                              <1> 	;
  3667                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3668                              <1> 	;	to the user with the file descriptor/number 
  3669                              <1> 	;	(index to u.fp list).
  3670                              <1> 	;
  3671                              <1> 	;call	arg2
  3672                              <1> 	; * name - 'u.namep' points to address of file/path name
  3673                              <1> 	;          in the user's program segment ('u.segmnt')
  3674                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3675                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3676                              <1> 	;          which is on top of stack.
  3677                              <1> 	;
  3678                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3679                              <1> 			    ; / on stack
  3680 00003F4D 891D[D06E0000]      <1> 	mov	[u.namep], ebx ; file name address
  3681                              <1> 	;push	cx ; mode
  3682                              <1> 	; 24/12/2021
  3683 00003F53 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3684 00003F54 E8790A0000          <1> 	call 	namei        	
  3685                              <1> 		; jsr r0,namei / get the i-number
  3686                              <1>         ;and	ax, ax
  3687                              <1> 	;jz	short syscreat_2	       	
  3688 00003F59 721B                <1> 	jc	short syscreat_2
  3689                              <1> 		; br  2f / if file doesn't exist 2f
  3690                              <1> 	; 27/12/2015
  3691 00003F5B 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3692                              <1>         ;jb	syscreat_0 ; yes
  3693                              <1> 	; 24/12/2021
  3694 00003F5F 7305                <1> 	jnb	short syscreat_1
  3695 00003F61 E954FFFFFF          <1> 	jmp	syscreat_0
  3696                              <1> syscreat_1:
  3697 00003F66 66F7D8              <1> 	neg 	ax
  3698                              <1>         	; neg r1 / if file already exists make i-number 
  3699                              <1> 		       ; / negative (open for writing)
  3700 00003F69 E8AD190000          <1> 	call	iopen
  3701                              <1>         	; jsr r0,iopen /
  3702 00003F6E E850130000          <1> 	call	itrunc
  3703                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3704                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3705                              <1> 	; 04/12/2021
  3706 00003F73 59                  <1> 	pop	ecx
  3707                              <1> 	; 08/01/2022
  3708 00003F74 EB0E                <1> 	jmp	short syscreat_3
  3709                              <1>         ;jmp	sysopen_1
  3710                              <1>         	; br op0
  3711                              <1> syscreat_2: ; 2: / file doesn't exist
  3712                              <1> 	;pop	ax
  3713                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3714                              <1> 	; 24/12/2021
  3715 00003F76 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3716 00003F77 30E4                <1> 	xor	ah, ah	
  3717                              <1>         	; bic $!377,r1 / clear upper byte
  3718 00003F79 E8170D0000          <1> 	call 	maknod
  3719                              <1>         	; jsr r0,maknod / make an i-node for this file
  3720 00003F7E 66A1[EA6E0000]      <1> 	mov	ax, [u.dirbuf]
  3721                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3722                              <1> 			        ; / for this new file in r1
  3723                              <1> syscreat_3:
  3724 00003F84 E93EFFFFFF          <1>         jmp     sysopen_1
  3725                              <1>         	; br op0 / open the file
  3726                              <1> 
  3727                              <1> sysmkdir: ; < make directory >
  3728                              <1> 	; 26/02/2022
  3729                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3730                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3731                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3732                              <1> 	;
  3733                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3734                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3735                              <1> 	; The special entries '.' and '..' are not present.
  3736                              <1> 	; Errors are indicated if the directory already exists or		
  3737                              <1> 	; user is not the super user. 
  3738                              <1> 	;
  3739                              <1> 	; Calling sequence:
  3740                              <1> 	;	sysmkdir; name; mode
  3741                              <1> 	; Arguments:
  3742                              <1> 	;	name - points to the name of the directory
  3743                              <1> 	;	mode - mode of the directory
  3744                              <1> 	; Inputs: (arguments)
  3745                              <1> 	; Outputs: -
  3746                              <1> 	;    (sets 'directory' flag to 1; 
  3747                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3748                              <1> 	; ...............................................................
  3749                              <1> 	;				
  3750                              <1> 	; Retro UNIX 8086 v1 modification: 
  3751                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3752                              <1> 	;	* 1st argument, name is pointed to by BX register
  3753                              <1> 	;	* 2nd argument, mode is in CX register
  3754                              <1> 	;
  3755                              <1> 		
  3756                              <1> ; / make a directory
  3757                              <1> 
  3758                              <1> 	;call	arg2
  3759                              <1> 	; * name - 'u.namep' points to address of file/path name
  3760                              <1> 	;          in the user's program segment ('u.segmnt')
  3761                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3762                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3763                              <1> 	;          which is on top of stack.
  3764                              <1> 
  3765                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3766                              <1> 			    ; / on stack
  3767 00003F89 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  3768                              <1> 	;push	cx ; mode
  3769                              <1> 	; 24/12/2021
  3770 00003F8F 51                  <1> 	push	ecx ; cx = mode
  3771 00003F90 E83D0A0000          <1> 	call	namei
  3772                              <1>         	; jsr r0,namei / get the i-number
  3773                              <1>         	;     br .+4 / if file not found branch around error
  3774                              <1>         ;xor 	ax, ax
  3775                              <1> 	;jnz	error
  3776 00003F95 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3777                              <1> 	;jnc	error	
  3778                              <1> 		; br  error2 / directory already exists (error)
  3779 00003F97 803D[046F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3780                              <1>         	;tstb u.uid / is user the super user
  3781                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3782                              <1> 	;;jna	error
  3783                              <1> 	; 26/02/2022 (BugFix)
  3784 00003F9E 7721                <1> 	ja	short dir_access_err
  3785                              <1>         	;bne error2 / no, not allowed
  3786                              <1> 	;pop	ax
  3787                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3788                              <1> 	; 24/12/2021
  3789 00003FA0 58                  <1> 	pop	eax  ; ax = mode
  3790 00003FA1 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3791                              <1>         	;bic $!317,r1 / all but su and ex
  3792                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3793 00003FA5 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3794                              <1>         	;bis $40000,r1 / directory flag
  3795 00003FA8 E8E80C0000          <1> 	call	maknod
  3796                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3797                              <1> ;sysclose_sysret: ; 26/02/2022
  3798 00003FAD E942FBFFFF          <1> 	jmp	sysret
  3799                              <1>         	;br sysret2 /
  3800                              <1> dir_exists:
  3801                              <1> 	; 14/05/2015
  3802 00003FB2 C705[0D6F0000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3802 00003FBA 0000                <1>
  3803 00003FBC E913FBFFFF          <1> 	jmp	error
  3804                              <1> dir_access_err:
  3805                              <1> 	; 14/05/2015
  3806 00003FC1 C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3806 00003FC9 0000                <1>
  3807 00003FCB E904FBFFFF          <1> 	jmp	error
  3808                              <1> 
  3809                              <1> sysclose: ;<close file>
  3810                              <1> 	; 26/02/2022
  3811                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3812                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3813                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3814                              <1> 	;
  3815                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3816                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3817                              <1> 	; is put in r1 and 'fclose' is called.
  3818                              <1> 	;
  3819                              <1> 	; Calling sequence:
  3820                              <1> 	;	sysclose
  3821                              <1> 	; Arguments:
  3822                              <1> 	;	-  
  3823                              <1> 	; Inputs: *u.r0 - file descriptor
  3824                              <1> 	; Outputs: -
  3825                              <1> 	; ...............................................................
  3826                              <1> 	;				
  3827                              <1> 	; Retro UNIX 8086 v1 modification:
  3828                              <1> 	;	 The user/application program puts file descriptor
  3829                              <1> 	;        in BX register as 'sysclose' system call argument.
  3830                              <1> 	; 	 (argument transfer method 1)
  3831                              <1> 
  3832                              <1> 	; / close the file
  3833                              <1> 	
  3834 00003FD0 89D8                <1> 	mov 	eax, ebx
  3835 00003FD2 E887090000          <1> 	call 	fclose
  3836                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3837                              <1> 		; jsr r0,fclose / close the file
  3838                              <1>                	; br error2 / unknown file descriptor
  3839                              <1> 		; br sysret2
  3840                              <1> 	; 14/05/2015
  3841                              <1> 	;jnc	sysret
  3842                              <1> 	; 04/12/2021
  3843 00003FD7 7205                <1> 	jc	short sysclose_err
  3844 00003FD9 E916FBFFFF          <1> 	jmp	sysret
  3845                              <1> 	; 26/02/2022
  3846                              <1> 	;jnc	short sysclose_sysret
  3847                              <1> sysclose_err:
  3848 00003FDE C705[0D6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3848 00003FE6 0000                <1>
  3849 00003FE8 E9E7FAFFFF          <1> 	jmp	error
  3850                              <1> 
  3851                              <1> sysemt:
  3852                              <1> 	; 26/02/2022
  3853                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3854                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3855                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3856                              <1> 	;
  3857                              <1> 	; Retro UNIX 8086 v1 modification: 
  3858                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3859                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3860                              <1> 	;
  3861                              <1> 	; Retro UNIX 8086 v1 feature only!
  3862                              <1> 	;	Using purpose: Kernel will start without time-out
  3863                              <1> 	;	(internal clock/timer) functionality.
  3864                              <1> 	;	Then etc/init will enable clock/timer for
  3865                              <1> 	;	multi tasking. (Then it will not be disabled again
  3866                              <1> 	;	except hardware reset/restart.)
  3867                              <1> 	;
  3868                              <1> 
  3869 00003FED 803D[046F0000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3870                              <1> 	;;ja	error
  3871                              <1> 	;ja	badsys ; 14/05/2015
  3872                              <1> 	; 24/12/2021
  3873 00003FF4 7605                <1> 	jna	short emt_0 
  3874 00003FF6 E98BFBFFFF          <1> 	jmp	badsys
  3875                              <1> emt_0:
  3876                              <1> 	; 24/12/2021
  3877                              <1> 	;cli
  3878 00003FFB 21DB                <1> 	and	ebx, ebx
  3879 00003FFD 7429                <1> 	jz	short emt_2
  3880                              <1> 	; Enable multi tasking -time sharing-
  3881 00003FFF B8[4E4F0000]        <1> 	mov	eax, clock
  3882                              <1> 	; 26/02/2022
  3883 00004004 BA[4D0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3884                              <1> emt_1:
  3885 00004009 A3[12070000]        <1> 	mov	[x_timer], eax
  3886                              <1> 	; 26/02/2022 (Temporary)
  3887 0000400E 8915[16070000]      <1> 	mov	[x_rtci], edx
  3888 00004014 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3889 00004016 E851020000          <1> 	call	wttyc  ; clear video page
  3890 0000401B B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3891 0000401D E84A020000          <1> 	call	wttyc  ; clear video page
  3892                              <1> 	;
  3893 00004022 FB                  <1> 	sti
  3894 00004023 E9CCFAFFFF          <1> 	jmp	sysret
  3895                              <1> emt_2:
  3896                              <1> 	; Disable multi tasking -time sharing-
  3897 00004028 B8[1E070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3898                              <1> 	; 26/02/2022
  3899 0000402D BA[540A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3900                              <1> 	;
  3901 00004032 EBD5                <1> 	jmp	short emt_1
  3902                              <1> 
  3903                              <1> 	; Original UNIX v1 'sysemt' routine
  3904                              <1> ;sysemt:
  3905                              <1>         ;
  3906                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3907                              <1> 			 ; / in loc 30
  3908                              <1>         ;cmp    30,$core / was the argument a lower address 
  3909                              <1> 			; / than core
  3910                              <1>         ;blo    1f / yes, rtssym
  3911                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3912                              <1> 			; / and less than "ecore"
  3913                              <1>         ;blo    2f / yes, sysret2
  3914                              <1> ;1:
  3915                              <1>         ;mov    $rtssym,30
  3916                              <1> ;2:
  3917                              <1>         ;br     sysret2
  3918                              <1> 
  3919                              <1> sysilgins:
  3920                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3921                              <1> 	; 03/06/2013
  3922                              <1> 	; Retro UNIX 8086 v1 modification: 
  3923                              <1> 	;	not a valid system call ! (not in use)
  3924                              <1> 	;
  3925 00004034 E94DFBFFFF          <1> 	jmp	badsys
  3926                              <1> 	;jmp	error
  3927                              <1> 	;;jmp 	sysret
  3928                              <1> 
  3929                              <1> 	; Original UNIX v1 'sysemt' routine
  3930                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3931                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3932                              <1> 			  ;/ put it in loc 8.,
  3933                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3934                              <1> 		       ; / trap address
  3935                              <1>         ;blo    1f / is the address a user core address?  
  3936                              <1> 		; / yes, go to 2f
  3937                              <1>         ;cmp    10,$ecore
  3938                              <1>         ;blo    2f
  3939                              <1> ;1:
  3940                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3941                              <1> 		    ; / instruction trap address for the system
  3942                              <1> ;2:
  3943                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3944                              <1> 
  3945                              <1> sysmdate: ; < change the modification time of a file >
  3946                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3947                              <1> 	;	(ECX input)
  3948                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3949                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3950                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3951                              <1> 	;
  3952                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3953                              <1> 	; file into core. The user is checked if he is the owner 
  3954                              <1> 	; or super user. If he is neither an error occurs.
  3955                              <1> 	; 'setimod' is then called to set the i-node modification
  3956                              <1> 	; byte and the modification time, but the modification time
  3957                              <1> 	; is overwritten by whatever get put on the stack during
  3958                              <1> 	; a 'systime' system call. This calls are restricted to
  3959                              <1> 	; the super user.		
  3960                              <1> 	;
  3961                              <1> 	; Calling sequence:
  3962                              <1> 	;	sysmdate; name
  3963                              <1> 	; Arguments:
  3964                              <1> 	;	name - points to the name of file
  3965                              <1> 	; Inputs: (arguments)
  3966                              <1> 	; Outputs: -
  3967                              <1> 	; ...............................................................
  3968                              <1> 	;				
  3969                              <1> 	; Retro UNIX 8086 v1 modification: 
  3970                              <1> 	;	 The user/application program puts address 
  3971                              <1> 	;	 of the file name in BX register 
  3972                              <1> 	;	 as 'sysmdate' system call argument.
  3973                              <1> 	;
  3974                              <1> ; / change the modification time of a file
  3975                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3976 00004039 891D[D06E0000]      <1>         mov	[u.namep], ebx
  3977                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3978 0000403F 890D[406B0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3979 00004045 E888090000          <1> 	call	namei
  3980                              <1> 		; jsr r0,namei / get its i-number
  3981                              <1> 	;;jc	error       
  3982                              <1> 	;	; br error2 / no, such file
  3983                              <1> 	;jc	fnotfound ; file not found !
  3984                              <1> 	; 24/12/2021
  3985 0000404A 7305                <1> 	jnc	short mdate_0
  3986 0000404C E99BFEFFFF          <1> 	jmp	fnotfound
  3987                              <1> mdate_0:
  3988 00004051 E841110000          <1> 	call	iget
  3989                              <1> 		; jsr r0,iget / get i-node into core
  3990 00004056 A0[046F0000]        <1> 	mov	al, [u.uid]
  3991 0000405B 3A05[BB6B0000]      <1> 	cmp	al, [i.uid]
  3992                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3993 00004061 7413                <1> 	je	short mdate_1
  3994                              <1>         	; beq 1f / yes
  3995 00004063 20C0                <1> 	and	al, al
  3996                              <1> 		; tstb u.uid / no, is user the super user
  3997                              <1> 	;jnz	error
  3998                              <1> 		; bne error2 / no, error
  3999 00004065 740F                <1> 	jz	short mdate_1
  4000 00004067 C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4000 0000406F 0000                <1>
  4001                              <1> sysstty_err:	; 04/02/2022
  4002 00004071 E95EFAFFFF          <1> 	jmp	error
  4003                              <1> mdate_1: ;1:
  4004 00004076 E826120000          <1> 	call	setimod
  4005                              <1>         	; jsr r0,setimod / fill in modification data,
  4006                              <1> 		               ; / time etc.
  4007 0000407B BE[406B0000]        <1> 	mov	esi, p_time
  4008 00004080 BF[D26B0000]        <1> 	mov	edi, i.mtim
  4009 00004085 A5                  <1> 	movsd
  4010                              <1> 		; mov 4(sp),i.mtim / move present time to
  4011                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4012 00004086 E969FAFFFF          <1>         jmp	sysret
  4013                              <1> 		; br sysret2
  4014                              <1> 
  4015                              <1> 	; 04/02/2022
  4016                              <1> sysstty_err_s:
  4017 0000408B 880D[B86E0000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4018 00004091 EBDE                <1> 	jmp	short sysstty_err
  4019                              <1> 
  4020                              <1> sysstty: ; < set tty status and mode >
  4021                              <1> 	; 26/02/2022
  4022                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4023                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4024                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4025                              <1> 	; 17/11/2015
  4026                              <1> 	; 12/11/2015
  4027                              <1> 	; 29/10/2015
  4028                              <1> 	; 17/10/2015
  4029                              <1> 	; 13/10/2015
  4030                              <1> 	; 29/06/2015
  4031                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4032                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4033                              <1> 	;
  4034                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4035                              <1> 	; whose file descriptor is in (u.r0).
  4036                              <1> 	;
  4037                              <1> 	; Calling sequence:
  4038                              <1> 	;	sysstty; arg
  4039                              <1> 	; Arguments:
  4040                              <1> 	;	arg - address of 3 consequitive words that contain
  4041                              <1> 	;	      the source of status data	
  4042                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4043                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4044                              <1> 	; ...............................................................
  4045                              <1> 	;	
  4046                              <1> 	; Retro UNIX 8086 v1 modification: 
  4047                              <1> 	;	'sysstty' system call will set the tty
  4048                              <1> 	;	(clear keyboard buffer and set cursor position)
  4049                              <1> 	;	 in following manner:
  4050                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4051                              <1> 	;
  4052                              <1> 	; Inputs:
  4053                              <1> 	;	BX = 0 --> means
  4054                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4055                              <1> 	;	      set cursor position for console tty, only 
  4056                              <1> 	;	      CH will be ignored (char. will not be written)	
  4057                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4058                              <1> 	;	      set console tty for (current) process
  4059                              <1> 	;	      CL = tty number (0 to 9)
  4060                              <1> 	;	      (If CH = 0, character will not be written)			
  4061                              <1> 	;          If CH > 0 (CL < FFh)	
  4062                              <1> 	;             CL = tty number (0 to 9)
  4063                              <1> 	;	      CH = character will be written
  4064                              <1> 	;	        at requested cursor position (in DX)	
  4065                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4066                              <1>   	;		(only tty number 0 to 7) 
  4067                              <1> 	;          DL = communication parameters (for serial ports) 
  4068                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4069                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4070                              <1> 	;			or set cursor position	
  4071                              <1> 	;	   DH = 0FFh -> DL is not valid
  4072                              <1> 	;		do not set serial port parameters 
  4073                              <1> 	;		or do not set cursor position
  4074                              <1> 	;
  4075                              <1> 	;	BX > 0 --> points to name of tty
  4076                              <1> 	;    	   CH > 0 -->
  4077                              <1> 	;		CH = character will be written in current 
  4078                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4079                              <1> 	;	     	or character will be sent to serial port
  4080                              <1> 	;	     	(for tty number 8 or 9)
  4081                              <1> 	;		CL = color of the character if tty number < 8.
  4082                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4083                              <1> 	;		set mode (tty 8 to 9) or 
  4084                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4085                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4086                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4087                              <1> 	;		(DL is not valid)
  4088                              <1> 	;	   DL = communication parameters 
  4089                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4090                              <1> 	;
  4091                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4092                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4093                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4094                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4095                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4096                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4097                              <1> 	;
  4098                              <1> 	; Outputs:
  4099                              <1> 	;	cf = 0 -> OK
  4100                              <1> 	;	     AL = tty number (0 to 9)
  4101                              <1> 	;	     AH = line status if tty number is 8 or 9
  4102                              <1> 	;	     AH = process number (of the caller) 	
  4103                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4104                              <1> 	;	     AH = FFh if the tty is locked 
  4105                              <1> 	;		  (owned by another process)
  4106                              <1> 	;	        = process number (of the caller) 
  4107                              <1> 	;		  (if < FFh and tty number < 8)
  4108                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4109                              <1> 	;	     AH = line status if tty number is 8 or 9
  4110                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4111                              <1> 	;	
  4112                              <1> 
  4113                              <1> 	; 27/06/2015 (32 bit modifications)
  4114                              <1> 	; 14/01/2014
  4115 00004093 31C0                <1> 	xor 	eax, eax
  4116 00004095 6648                <1> 	dec	ax ; 17/10/2015
  4117 00004097 A3[B86E0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4118                              <1> 	;;;
  4119                              <1> 	; 01/02/2022
  4120 0000409C FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4121 0000409E 39C2                <1> 	cmp	edx, eax
  4122                              <1> 	;cmp	dx, ax ; 0FFFFh
  4123 000040A0 7521                <1> 	jne	short sysstty_18
  4124                              <1> 	; clear video page
  4125                              <1> 	; (CH must be 0)
  4126 000040A2 08ED                <1> 	or	ch, ch
  4127 000040A4 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4128 000040A6 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4129 000040A9 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4130 000040AB 20C9                <1> 	and	cl, cl
  4131 000040AD 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4132 000040AF 0FB635[076F0000]    <1> 	movzx	esi, byte [u.uno]
  4133 000040B6 8A8E[176C0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4134 000040BC 80F907              <1> 	cmp	cl, 7
  4135 000040BF 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4136                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4137 000040C1 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4138                              <1> sysstty_18:
  4139 000040C3 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4140                              <1> 	; cl = video page (tty) number		
  4141                              <1> 	;;;
  4142 000040C5 21DB                <1> 	and	ebx, ebx
  4143                              <1> 	;jnz	sysstty_6
  4144                              <1> 	; 01/02/2022
  4145 000040C7 7405                <1> 	jz	short sysstty_19
  4146 000040C9 E9C2000000          <1> 	jmp	sysstty_6
  4147                              <1> sysstty_19:
  4148                              <1> 	; set console tty
  4149                              <1> 	; 29/10/2015
  4150                              <1> 	; 17/01/2014 
  4151 000040CE 80F909              <1> 	cmp	cl, 9
  4152 000040D1 7613                <1> 	jna	short sysstty_0
  4153                              <1> 	; 17/11/2015
  4154 000040D3 80F9FF              <1> 	cmp	cl, 0FFh
  4155 000040D6 7202                <1> 	jb	short sysstty_13
  4156 000040D8 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4157                              <1> sysstty_13:
  4158 000040DA 8A1D[076F0000]      <1> 	mov	bl, [u.uno] ; process number
  4159 000040E0 8A8B[176C0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4160                              <1> sysstty_0:
  4161                              <1> 	; 29/06/2015
  4162                              <1> 	;push	dx
  4163                              <1> 	;push	cx
  4164                              <1> 	; 01/02/2022
  4165 000040E6 52                  <1> 	push	edx
  4166 000040E7 51                  <1> 	push	ecx
  4167 000040E8 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4168 000040EA 88C8                <1> 	mov	al, cl
  4169 000040EC A2[B86E0000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4170 000040F1 E8BF180000          <1> 	call	ottyp
  4171                              <1> 	; 01/02/2022
  4172 000040F6 59                  <1> 	pop	ecx
  4173 000040F7 5A                  <1> 	pop	edx
  4174                              <1> 	;pop	cx
  4175                              <1> 	;pop	dx
  4176                              <1> 	;
  4177 000040F8 7220                <1> 	jc	short sysstty_pd_err
  4178                              <1> 	;
  4179                              <1> 	; 26/02/2022 (Bug! BugFix)
  4180                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4181                              <1> 	;
  4182 000040FA 80F908              <1> 	cmp	cl, 8
  4183 000040FD 720C                <1> 	jb	short sysstty_2
  4184                              <1> 	;
  4185 000040FF 80FEFF              <1> 	cmp	dh, 0FFh
  4186 00004102 7407                <1> 	je	short sysstty_2
  4187                              <1> 		; set communication parameters for serial ports
  4188                              <1> 
  4189                              <1> ; 01/02/2022
  4190                              <1> ;	; 29/10/2015
  4191                              <1> ;	mov	ah, dl ; communication parameters
  4192                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4193                              <1> ;		;			 THRE int + RDA int 
  4194                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4195                              <1> ;		;			 THRE int + RDA int 
  4196                              <1> ;	sub	al, al ; 0
  4197                              <1> ;	; 12/07/2014
  4198                              <1> ;	cmp	cl, 9
  4199                              <1> ;	jb	short sysstty_1
  4200                              <1> ;	inc	al
  4201                              <1> ;sysstty_1:
  4202                              <1> ;	; 01/02/2022
  4203                              <1> ;	push	ecx
  4204                              <1> ;	;push	cx
  4205                              <1> ;	; 29/06/2015	
  4206                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4207                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4208                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4209                              <1> ;	; 01/02/2022
  4210                              <1> ;	pop	ecx	
  4211                              <1> ;	;pop	cx
  4212                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4213                              <1> 
  4214                              <1> 	; 01/02/2022
  4215 00004104 E830010000          <1> 	call	sysstty_scp
  4216 00004109 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4217                              <1> 
  4218                              <1> sysstty_2:
  4219                              <1> 	; 17/01/2014
  4220 0000410B 20ED                <1> 	and	ch, ch 	; set cursor position 
  4221                              <1> 			; or comm. parameters ONLY
  4222 0000410D 7527                <1> 	jnz	short sysstty_3
  4223                              <1> 	; 01/02/2022
  4224 0000410F 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4225 00004113 7214                <1> 	jb	short sysstty_20
  4226                              <1> 	; clear screen (video page)
  4227 00004115 E93B010000          <1> 	jmp	sysstty_14
  4228                              <1> 
  4229                              <1> sysstty_pd_err: ; 29/06/2015
  4230                              <1> 	; 'permission denied !' error
  4231 0000411A C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4231 00004122 0000                <1>
  4232 00004124 E9ABF9FFFF          <1> 	jmp	error
  4233                              <1> 
  4234                              <1> sysstty_20:
  4235 00004129 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4236 00004130 888B[176C0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4237                              <1> sysstty_3:
  4238                              <1> 	; 16/01/2014
  4239 00004136 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4240                              <1> 	; 17/11/2015
  4241 00004138 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4242 0000413A 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4243                              <1> 	;jna	sysstty_9
  4244                              <1> 	; 01/02/2022
  4245 0000413C 7705                <1> 	ja	short sysstty_12
  4246 0000413E E9C5000000          <1> 	jmp	sysstty_9
  4247                              <1> 
  4248                              <1> sysstty_12:
  4249                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4250                              <1> 	; (Set specified serial port as console tty port)
  4251                              <1> 	; CH = character to be written
  4252                              <1> 	; 15/04/2014
  4253                              <1> 	; CH = 0 --> initialization only
  4254                              <1> 	; AL = character
  4255                              <1> 	; 26/06/2014
  4256 00004143 880D[0C6F0000]      <1> 	mov	[u.ttyn], cl
  4257                              <1> 	; 12/07/2014
  4258 00004149 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4259                              <1> 	; 02/02/2022
  4260 0000414B FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4261 0000414D 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4262 0000414F FEC8                <1> 	dec	al  ; 1 -> 0	
  4263                              <1> 	;and	al, al
  4264 00004151 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4265                              <1>  	; 04/07/2014
  4266 00004153 E89D1E0000          <1> 	call 	sndc
  4267                              <1> 	; 12/07/2014
  4268 00004158 EB0C                <1> 	jmp	short sysstty_5
  4269                              <1> 
  4270                              <1> sysstty_4:
  4271                              <1> 	; 12/07/2014
  4272                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4273 0000415A 88E0                <1> 	mov	al, ah ; 29/06/2015
  4274 0000415C 2C08                <1> 	sub	al, 8
  4275                              <1> 	; 27/06/2015
  4276 0000415E E819F4FFFF          <1> 	call	sp_status ; get serial port status
  4277                              <1> 	; AL = Line status, AH = Modem status
  4278                              <1> 	; 12/11/2015
  4279 00004163 3C80                <1> 	cmp	al, 80h
  4280 00004165 F5                  <1> 	cmc
  4281                              <1> sysstty_5:
  4282 00004166 66A3[B96E0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4283                              <1> 		; EAX bits 16-23 = modem status	
  4284 0000416C 9C                  <1> 	pushf
  4285 0000416D 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4286 0000416F A0[0C6F0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4287 00004174 E863190000          <1> 	call	cttyp
  4288 00004179 9D                  <1> 	popf
  4289                              <1> 	;jnc	sysret ; time out error 
  4290                              <1> 	; 01/02/2022
  4291 0000417A 7205                <1> 	jc	short sysstty_tmout_err
  4292 0000417C E973F9FFFF          <1> 	jmp	sysret
  4293                              <1> 
  4294                              <1> sysstty_tmout_err:
  4295 00004181 C705[0D6F0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4295 00004189 0000                <1>
  4296 0000418B E944F9FFFF          <1> 	jmp	error
  4297                              <1> 
  4298                              <1> sysstty_6:
  4299                              <1> 	;push	dx
  4300                              <1> 	;push	cx
  4301                              <1> 	; 01/02/2022
  4302 00004190 52                  <1> 	push	edx
  4303 00004191 51                  <1> 	push	ecx
  4304 00004192 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  4305 00004198 E835080000          <1> 	call	namei
  4306                              <1> 	; 01/02/2022
  4307 0000419D 59                  <1> 	pop	ecx
  4308 0000419E 5A                  <1> 	pop	edx
  4309                              <1> 	;pop	cx
  4310                              <1> 	;pop	dx
  4311 0000419F 7258                <1> 	jc	short sysstty_inv_dn
  4312                              <1> 	;
  4313 000041A1 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4314 000041A5 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4315                              <1> 	;
  4316 000041A7 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4317                              <1> 		       ; /dev/COM1, /dev/COM2
  4318 000041A9 7204                <1> 	jb	short sysstty_7
  4319 000041AB 2C0A                <1> 	sub	al, 10
  4320 000041AD EB11                <1> 	jmp	short sysstty_8
  4321                              <1> 
  4322                              <1> sysstty_7:
  4323 000041AF 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4324 000041B1 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4325 000041B3 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4326 000041BA 8A83[176C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4327                              <1> sysstty_8:
  4328                              <1> 	; 26/02/2022
  4329                              <1> 	; (ebx < 256)	
  4330 000041C0 A2[B86E0000]        <1> 	mov	[u.r0], al
  4331                              <1> 	; 01/02/2022
  4332                              <1> 	;push	dx
  4333                              <1> 	;push	ax
  4334                              <1> 	;push	cx
  4335 000041C5 52                  <1> 	push	edx
  4336 000041C6 50                  <1> 	push	eax
  4337 000041C7 51                  <1> 	push	ecx	
  4338 000041C8 E8E8170000          <1> 	call	ottyp
  4339 000041CD 59                  <1> 	pop	ecx
  4340 000041CE 58                  <1> 	pop	eax
  4341 000041CF 5A                  <1> 	pop	edx
  4342                              <1> 	;pop	cx
  4343                              <1> 	;pop	ax
  4344                              <1> 	;pop	dx
  4345                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4346                              <1> 	; 01/02/2022
  4347 000041D0 7305                <1> 	jnc	short sysstty_21
  4348 000041D2 E943FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4349                              <1> sysstty_21:
  4350                              <1> 	; 29/10/2015
  4351 000041D7 86E9                <1> 	xchg 	ch, cl
  4352                              <1> 		; cl = character, ch = color code
  4353 000041D9 86C1                <1> 	xchg	al, cl
  4354                              <1> 		; al = character, cl = tty number
  4355 000041DB 80F907              <1> 	cmp	cl, 7
  4356                              <1> 	;ja	sysstty_12
  4357                              <1> 	; 01/02/2022
  4358 000041DE 7628                <1> 	jna	short sysstty_16
  4359                              <1> ;;
  4360 000041E0 80FEFF              <1> 	cmp	dh, 0FFh
  4361 000041E3 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4362                              <1> 
  4363                              <1> ; 01/02/2022
  4364                              <1> ;	; 29/10/2015
  4365                              <1> ;	mov	ah, dl ; communication parameters
  4366                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4367                              <1> ;		;			 THRE int + RDA int 
  4368                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4369                              <1> ;		;			 THRE int + RDA int 
  4370                              <1> ;	sub	al, al ; 0
  4371                              <1> ;	; 12/07/2014
  4372                              <1> ;	cmp	cl, 9
  4373                              <1> ;	jb	short sysstty_1
  4374                              <1> ;	inc	al
  4375                              <1> ;sysstty_1:
  4376                              <1> ;	; 01/02/2022
  4377                              <1> ;	push	ecx
  4378                              <1> ;	;push	cx
  4379                              <1> ;	; 29/06/2015	
  4380                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4381                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4382                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4383                              <1> ;	; 01/02/2022
  4384                              <1> ;	pop	ecx	
  4385                              <1> ;	;pop	cx
  4386                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4387                              <1> 
  4388                              <1> 	; 02/02/2022
  4389 000041E5 88C5                <1> 	mov	ch, al ; save char
  4390                              <1> 	; 01/02/2022
  4391 000041E7 E84D000000          <1> 	call	sysstty_scp
  4392 000041EC 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4393                              <1> 	; 02/02/2022
  4394 000041EE 88E8                <1> 	mov	al, ch ; restore char
  4395                              <1> sysstty_22:
  4396                              <1> 	; 01/02/2022
  4397 000041F0 08ED                <1> 	or	ch, ch
  4398 000041F2 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4399                              <1> 	; send char to (serial port) terminal
  4400                              <1> 	; al = character
  4401                              <1> 	; cl = tty number (8 or 9)
  4402 000041F4 E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4403                              <1> 
  4404                              <1> sysstty_inv_dn: 
  4405                              <1> 	; 27/06/2015
  4406                              <1> 	; Invalid device name (not a tty) ! error
  4407                              <1> 	; (Device is not a tty or device name not found)
  4408 000041F9 C705[0D6F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4408 00004201 0000                <1>
  4409 00004203 E9CCF8FFFF          <1> 	jmp	error 
  4410                              <1> 
  4411                              <1> sysstty_16:
  4412                              <1> 	; 26/02/2022
  4413                              <1> 	; 16/01/2014
  4414                              <1> 	;xor	bh, bh
  4415                              <1> 	; 02/02/2022
  4416                              <1> sysstty_9: 	; tty 0 to tty 7
  4417                              <1> 	; al = character
  4418                              <1> 	; ch = color/attribute ; 01/02/2022
  4419                              <1> 	;
  4420                              <1> 	; 26/02/2022 (BugFix)
  4421                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4422 00004208 29DB                <1> 	sub	ebx, ebx ; *
  4423 0000420A 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4424 0000420D 740B                <1> 	je	short sysstty_10
  4425                              <1> 	; 02/02/2022
  4426 0000420F 51                  <1> 	push	ecx
  4427 00004210 50                  <1> 	push	eax
  4428                              <1> 	;push	cx
  4429                              <1> 	;push	ax	
  4430                              <1> 	;movzx	ebx, cl
  4431 00004211 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4432 00004213 E8B9D2FFFF          <1> 	call	set_cpos
  4433                              <1> 	;pop	ax
  4434                              <1> 	;pop	cx
  4435                              <1> 	; 02/02/2022
  4436 00004218 58                  <1> 	pop	eax
  4437 00004219 59                  <1> 	pop	ecx
  4438                              <1> sysstty_10: 
  4439                              <1> 	; 29/10/2015
  4440 0000421A 08C0                <1> 	or	al, al ; character
  4441 0000421C 740D                <1> 	jz      short sysstty_11 ; al = 0
  4442                              <1> 	; 17/11/2015
  4443 0000421E 3CFF                <1> 	cmp	al, 0FFh
  4444 00004220 7309                <1> 	jnb	short sysstty_11
  4445                              <1> 		; ch > 0 and ch < FFh
  4446                              <1> 	; write a character at current cursor position
  4447 00004222 88EC                <1> 	mov	ah, ch ; color/attribute
  4448                              <1> 	; 12/07/2014
  4449                              <1> 	;push	cx
  4450                              <1> 	; 02/02/2022
  4451 00004224 51                  <1> 	push	ecx
  4452 00004225 E893D3FFFF          <1> 	call	write_c_current
  4453                              <1> 	;pop	cx
  4454                              <1> 	; 02/02/2022
  4455 0000422A 59                  <1> 	pop	ecx
  4456                              <1> sysstty_11:
  4457                              <1> 	; 14/01/2014
  4458 0000422B 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4459                              <1> 	; 18/01/2014
  4460                              <1> 	;movzx	eax, cl ; 27/06/2015
  4461 0000422D 88C8                <1> 	mov	al, cl
  4462 0000422F E8A8180000          <1> 	call	cttyp
  4463 00004234 E9BBF8FFFF          <1> 	jmp	sysret
  4464                              <1> 
  4465                              <1> sysstty_scp:
  4466                              <1> 	; 02/02/2022
  4467                              <1> 	; set communication parameters (for COM1 or COM2)
  4468                              <1> 	; 01/02/2022
  4469                              <1> 	;
  4470                              <1> 	; 29/10/2015
  4471 00004239 88D4                <1> 	mov	ah, dl ; communication parameters
  4472                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4473                              <1> 		;			 THRE int + RDA int 
  4474                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4475                              <1> 		;			 THRE int + RDA int 
  4476 0000423B 28C0                <1> 	sub	al, al ; 0
  4477                              <1> 	; 12/07/2014
  4478 0000423D 80F909              <1> 	cmp	cl, 9
  4479 00004240 7202                <1> 	jb	short sysstty_1
  4480 00004242 FEC0                <1> 	inc	al
  4481                              <1> sysstty_1:
  4482                              <1> 	; 02/02/2022
  4483 00004244 52                  <1> 	push	edx
  4484                              <1> 	; 01/02/2022
  4485 00004245 51                  <1> 	push	ecx
  4486                              <1> 	;push	cx
  4487                              <1> 	; 29/06/2015	
  4488 00004246 E839F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4489 0000424B 66890D[B96E0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4490                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4491                              <1> 	; 01/02/2022
  4492 00004252 59                  <1> 	pop	ecx	
  4493                              <1> 	;pop	cx
  4494 00004253 5A                  <1> 	pop	edx ; 02/02/2022
  4495                              <1> 	; 01/02/2022
  4496                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4497 00004254 C3                  <1> 	retn
  4498                              <1> 
  4499                              <1> sysstty_14:
  4500                              <1> 	; 26/02/2022
  4501                              <1> 	; 02/02/2022
  4502                              <1> 	; ch = 0
  4503                              <1> 	; cl = video page
  4504                              <1> 	;
  4505                              <1> 	; dx = 0FFFFh
  4506                              <1> 	; clear screen (video page)
  4507                              <1> 	;
  4508                              <1> 
  4509                              <1> 	; 02/02/2022
  4510                              <1> 	; clear screen
  4511                              <1> 	;
  4512                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4513                              <1> 	; clear video page
  4514                              <1> 
  4515                              <1> 	; 26/02/2022
  4516 00004255 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4517                              <1> 
  4518                              <1> 	; clear video page
  4519 00004257 E810000000          <1> 	call	wttyc ; 26/02/2022
  4520                              <1> 
  4521                              <1> 	; 26/02/2022
  4522 0000425C 88D8                <1> 	mov	al, bl
  4523 0000425E 8A25[076F0000]      <1> 	mov	ah, [u.uno]
  4524 00004264 66A3[B86E0000]      <1> 	mov	[u.r0], ax
  4525 0000426A EBBF                <1> 	jmp	short sysstty_11
  4526                              <1> 
  4527                              <1> wttyc:
  4528                              <1> 	; 23/02/2022
  4529                              <1> 	; (clear video page)
  4530                              <1> 	; INPUT:
  4531                              <1> 	;  bl = video page (0 to 7)
  4532                              <1> 	;
  4533                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4534                              <1> 
  4535                              <1> 	;xor	dx, dx ; column 0, row 0
  4536                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4537                              <1> 	;
  4538                              <1> ;	movzx	ebx, cl
  4539                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4540                              <1> 
  4541                              <1> ;	shl 	bl, 1 
  4542                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4543                              <1> ;		; AL = lock value (0 or process number)
  4544                              <1> ;	or	al, al
  4545                              <1> ;	jz	short @f
  4546                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4547                              <1> ;	jne	short sysstty_15
  4548                              <1> ;		; only the owner can clear its video page
  4549                              <1> ;	xor	al, al ; 0
  4550                              <1> ;@@:
  4551                              <1> ;	;mov	bl, cl		
  4552                              <1> ;	shr	bl, 1 
  4553                              <1> 
  4554 0000426C 30C0                <1> 	xor	al, al	; 0
  4555 0000426E B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4556                              <1> 
  4557                              <1> 	; scroll_up input:
  4558                              <1> 	;
  4559                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4560                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4561                              <1> 	; ah = attribute to be used on blanked line
  4562                              <1> 	; bl = video page number (0 to 7)
  4563                              <1> 
  4564 00004270 E8E6D2FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4565                              <1> 
  4566                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4567                              <1> 
  4568                              <1> 	; bl = video page number (0 to 7)
  4569                              <1> 	;xor	dx, dx ; column 0, row 0
  4570                              <1> 	; 02/02/2022
  4571 00004275 31D2                <1> 	xor	edx, edx
  4572                              <1> 	; 26/02/2022
  4573                              <1> 	;call	set_cpos
  4574                              <1> 	;retn
  4575 00004277 E955D2FFFF          <1> 	jmp	set_cpos
  4576                              <1> 
  4577                              <1> 	;mov	al, bl
  4578                              <1> 	;mov	ah, [u.uno]
  4579                              <1> 	;mov	[u.r0], ax
  4580                              <1> 	;jmp	short sysstty_11
  4581                              <1> 
  4582                              <1> ;sysstty_15:
  4583                              <1> ;	; 30/01/2022
  4584                              <1> ;	; permission (denied) error
  4585                              <1> ;	;xor	dl, dl ; sysstty call sign
  4586                              <1> ;	mov	al, cl
  4587                              <1> ;	sub	ah, ah ; 0
  4588                              <1> ;	call	cttyp
  4589                              <1> ;	jmp	error
  4590                              <1> 
  4591                              <1> ; Original UNIX v1 'sysstty' routine:
  4592                              <1> ; gtty:
  4593                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4594                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4595                              <1> 	; 		/ r2 has source
  4596                              <1>         ;mov    r2,-(sp)
  4597                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4598                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4599                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4600                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4601                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4602                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4603                              <1>         ;       br .+4 / list empty, skip branch
  4604                              <1>         ;br     1b / get another character until list is empty
  4605                              <1>         ;mov    0b,r1 / move cc offset to r1
  4606                              <1>         ;inc    r1 / bump it for output clist
  4607                              <1>         ;tstb   cc(r1) / is it 0
  4608                              <1>         ;beq    1f / yes, no characters to output
  4609                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4610                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4611                              <1>         ;br     1b / try to calm it down again
  4612                              <1> ;1:
  4613                              <1>         ;mov    (sp)+,r1
  4614                              <1>         ;mov    (sp)+,r2 / restore registers
  4615                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4616                              <1>         ;beq    1f / if 0, 1f
  4617                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4618                              <1>         ;                   / control status register
  4619                              <1> ;1:
  4620                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4621                              <1>         ;beq    1f / if 0 1f
  4622                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4623                              <1> 	;		    / control status reg
  4624                              <1> ;1:
  4625                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4626                              <1>         ;jmp     sysret2 / return to user
  4627                              <1> 
  4628                              <1> sysgtty: ; < get tty status >
  4629                              <1> 	; 26/02/2022
  4630                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4631                              <1> 	;	    ((32 bit reg push/pop))
  4632                              <1> 	; 23/11/2015
  4633                              <1> 	; 29/10/2015
  4634                              <1> 	; 17/10/2015
  4635                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4636                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4637                              <1> 	;
  4638                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4639                              <1> 	; It stores in the three words addressed by it's argument
  4640                              <1> 	; the status of the typewriter whose file descriptor
  4641                              <1> 	; in (u.r0).
  4642                              <1> 	;
  4643                              <1> 	; Calling sequence:
  4644                              <1> 	;	sysgtty; arg
  4645                              <1> 	; Arguments:
  4646                              <1> 	;	arg - address of 3 words destination of the status
  4647                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4648                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4649                              <1> 	; ...............................................................
  4650                              <1> 	;	
  4651                              <1> 	; Retro UNIX 8086 v1 modification: 
  4652                              <1> 	;	'sysgtty' system call will return status of tty
  4653                              <1> 	;	(keyboard, serial port and video page status)
  4654                              <1> 	;	 in following manner:
  4655                              <1> 	;
  4656                              <1> 	; Inputs:
  4657                              <1> 	;	BX = 0 --> means 
  4658                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4659                              <1> 	;	                 for (current) process
  4660                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4661                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4662                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4663                              <1> 	;	     CH > 0 -->	tty number + 1
  4664                              <1> 	;
  4665                              <1> 	;	BX > 0 --> points to name of tty
  4666                              <1> 	;	     CL = 0 --> return keyboard status
  4667                              <1> 	;	     CL = 1 --> return video page status
  4668                              <1> 	;	     CH = undefined		 
  4669                              <1> 	;
  4670                              <1> 	; Outputs:
  4671                              <1> 	;	cf = 0 ->
  4672                              <1> 	;
  4673                              <1> 	;	     AL = tty number from 0 to 9
  4674                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4675                              <1> 	;	     AH = 0 if the tty is free/unused
  4676                              <1> 	;	     AH = the process number of the caller 
  4677                              <1>  	;	     AH = FFh if the tty is locked by another process
  4678                              <1> 	;
  4679                              <1> 	;	  (if calling is for serial port status)
  4680                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4681                              <1> 	;		  (BH = modem status, BL = Line status)
  4682                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4683                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4684                              <1> 	;
  4685                              <1> 	;	  (if calling is for keyboard status)
  4686                              <1> 	;	     BX = current character in tty/keyboard buffer
  4687                              <1> 	;		  (BH = scan code, BL = ascii code)
  4688                              <1> 	;		  (BX=0 if there is not a waiting character)
  4689                              <1> 	;	     CX  is undefined
  4690                              <1> 	;
  4691                              <1> 	;	  (if calling is for video page status)	
  4692                              <1> 	;	     BX = cursor position on the video page
  4693                              <1> 	;		  if tty number < 8
  4694                              <1> 	;		  (BH = row, BL = column)
  4695                              <1> 	;	     CX = current character (in cursor position)
  4696                              <1> 	;		  on the video page of the tty 
  4697                              <1> 	;		  if tty number < 8
  4698                              <1> 	;		  (CH = color, CL = character)
  4699                              <1> 	;	
  4700                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4701                              <1> 	;
  4702                              <1> 	;	     AH = FFh if the caller is not owner of
  4703                              <1> 	;		  specified tty or console tty
  4704                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4705                              <1> 	;	     BX, CX are undefined if cf = 1
  4706                              <1> 	;
  4707                              <1> 	;	  (If tty number is 8 or 9)
  4708                              <1> 	;	     AL = tty number 
  4709                              <1> 	;	     AH = the process number of the caller 
  4710                              <1> 	;	     BX = serial port status
  4711                              <1> 	;  		 (BH = modem status, BL = Line status)
  4712                              <1> 	;	     CX = 0
  4713                              <1> 	;
  4714                              <1> 		
  4715                              <1> gtty:   ; get (requested) tty number
  4716                              <1> 	; 26/02/2022
  4717                              <1> 	; 17/10/2015
  4718                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4719                              <1> 	; 30/05/2013 - 12/07/2014
  4720                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4721                              <1> 	;
  4722                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4723                              <1> 	;
  4724                              <1> 	; 28/06/2015 (32 bit modifications)
  4725                              <1> 	; 16/01/2014
  4726 0000427C 31C0                <1> 	xor 	eax, eax
  4727 0000427E 6648                <1> 	dec	ax ; 17/10/2015
  4728 00004280 A3[B86E0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4729 00004285 80F901              <1> 	cmp	cl, 1
  4730 00004288 760F                <1> 	jna	short sysgtty_0
  4731                              <1> sysgtty_invp:
  4732                              <1> 	; 28/06/2015
  4733 0000428A C705[0D6F0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4733 00004292 0000                <1>
  4734 00004294 E93BF8FFFF          <1> 	jmp	error
  4735                              <1> sysgtty_0:	
  4736 00004299 21DB                <1> 	and	ebx, ebx
  4737 0000429B 742E                <1> 	jz	short sysgtty_1
  4738                              <1> 	;
  4739 0000429D 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  4740                              <1> 	;push	cx ; 23/11/2015
  4741 000042A3 51                  <1> 	push	ecx ; 24/12/2021
  4742 000042A4 E829070000          <1> 	call	namei
  4743 000042A9 59                  <1> 	pop	ecx
  4744                              <1> 	;pop	cx ; 23/11/2015
  4745 000042AA 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4746                              <1> 	;
  4747 000042AC 6683F801            <1> 	cmp	ax, 1
  4748 000042B0 7622                <1> 	jna	short sysgtty_2
  4749                              <1> 	; 26/02/2022
  4750 000042B2 20E4                <1> 	and	ah, ah
  4751 000042B4 7506                <1> 	jnz	short sysgtty_inv_dn
  4752                              <1> 	;sub	ax, 10
  4753 000042B6 2C0A                <1> 	sub	al, 10
  4754 000042B8 3C09                <1> 	cmp	al, 9
  4755                              <1> 	;cmp	ax, 9
  4756                              <1> 	;ja	short sysgtty_inv_dn
  4757                              <1> 	;mov	ch, al
  4758                              <1> 	;jmp	short sysgtty_4
  4759                              <1> 	; 23/11/2015
  4760 000042BA 7629                <1> 	jna	short sysgtty_4
  4761                              <1> sysgtty_inv_dn: 
  4762                              <1> 	; 28/06/2015
  4763                              <1> 	; Invalid device name (not a tty) ! error
  4764                              <1> 	; (Device is not a tty or device name not found)
  4765 000042BC C705[0D6F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4765 000042C4 0000                <1>
  4766 000042C6 E909F8FFFF          <1> 	jmp	error 
  4767                              <1> sysgtty_1:
  4768                              <1> 	; 16/01/2014
  4769 000042CB 80FD0A              <1> 	cmp	ch, 10
  4770 000042CE 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4771 000042D0 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4772 000042D2 790F                <1> 	jns	short sysgtty_3 ; not negative
  4773                              <1> 	;
  4774                              <1> sysgtty_2:
  4775                              <1> 	; get tty number of console tty
  4776 000042D4 8A25[076F0000]      <1> 	mov	ah, [u.uno]
  4777                              <1>  	; 28/06/2015
  4778 000042DA 0FB6DC              <1> 	movzx 	ebx, ah
  4779 000042DD 8AAB[176C0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4780                              <1> sysgtty_3:
  4781 000042E3 88E8                <1> 	mov	al, ch
  4782                              <1> sysgtty_4:
  4783 000042E5 A2[B86E0000]        <1> 	mov	[u.r0], al
  4784                              <1>  	; 28/06/2015
  4785                              <1> 	;cmp	al, 9
  4786                              <1> 	;ja	short sysgtty_invp
  4787 000042EA 8B2D[B46E0000]      <1> 	mov	ebp, [u.usp]
  4788                              <1> 	; 23/11/2015
  4789 000042F0 20C9                <1> 	and	cl, cl
  4790 000042F2 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4791 000042F4 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4792 000042F6 722E                <1> 	jb	short sysgtty_6 ; video page status
  4793                              <1> 	; serial port status
  4794                              <1> 	; 12/07/2014
  4795                              <1> 	;mov	dx, 0
  4796                              <1> 	;je	short sysgtty_5
  4797                              <1> 	;inc	dl
  4798                              <1> ;sysgtty_5:
  4799                              <1> 	; 28/06/2015
  4800 000042F8 2C08                <1> 	sub	al, 8
  4801 000042FA E87DF2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4802                              <1> 	; AL = Line status, AH = Modem status
  4803 000042FF 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4804 00004303 8A25[076F0000]      <1> 	mov	ah, [u.uno]
  4805 00004309 8825[B96E0000]      <1>         mov     [u.r0+1], ah
  4806                              <1> 	; 24/12/2021
  4807 0000430F 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4808                              <1> 				; (in ECX)
  4809 00004315 A880                <1> 	test	al, 80h
  4810 00004317 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4811 00004319 A801                <1> 	test	al, 1
  4812                              <1> 	;jz	sysret
  4813 0000431B 7404                <1> 	jz	short sysgtty_10
  4814 0000431D 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4815                              <1> sysgtty_10:
  4816 00004321 E9CEF7FFFF          <1> 	jmp	sysret
  4817                              <1> sysgtty_6:
  4818 00004326 A2[0C6F0000]        <1> 	mov	[u.ttyn], al ; tty number
  4819                              <1> 	;movzx	ebx, al
  4820 0000432B 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4821 0000432D D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4822                              <1> 	; 22/04/2014 - 29/06/2015
  4823 0000432F 81C3[446B0000]      <1>         add     ebx, ttyl
  4824 00004335 8A23                <1>  	mov	ah, [ebx]
  4825 00004337 3A25[076F0000]      <1> 	cmp	ah, [u.uno]
  4826 0000433D 7404                <1> 	je	short sysgtty_7
  4827 0000433F 20E4                <1> 	and	ah, ah
  4828                              <1> 	;jz	short sysgtty_7
  4829 00004341 7506                <1> 	jnz	short sysgtty_8
  4830                              <1> 	;mov	ah, 0FFh
  4831                              <1> sysgtty_7:
  4832 00004343 8825[B96E0000]      <1>         mov     [u.r0+1], ah
  4833                              <1> sysgtty_8:
  4834 00004349 08C9                <1> 	or	cl, cl
  4835 0000434B 7510                <1> 	jnz	short sysgtty_9
  4836 0000434D B001                <1> 	mov	al, 1  ; test a key is available
  4837 0000434F E8241C0000          <1> 	call	getc
  4838 00004354 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4839 00004358 E997F7FFFF          <1> 	jmp	sysret
  4840                              <1> sysgtty_9:
  4841 0000435D 8A1D[0C6F0000]      <1> 	mov	bl, [u.ttyn]
  4842                              <1> 	; bl = video page number
  4843 00004363 E8811D0000          <1> 	call 	get_cpos
  4844                              <1> 	; dx = cursor position
  4845 00004368 66895510            <1> 	mov	[ebp+16], dx ; bx
  4846                              <1> 	;mov	bl, [u.ttyn]
  4847                              <1> 	; bl = video page number
  4848 0000436C E8891D0000          <1> 	call	read_ac_current
  4849                              <1> 	; ax = character and attribute/color
  4850 00004371 66894518            <1> 	mov	[ebp+24], ax ; cx
  4851 00004375 E97AF7FFFF          <1> 	jmp	sysret
  4852                              <1> sysgtty_dnr_err:
  4853                              <1> 	; 'device not responding !' error	
  4854                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4855 0000437A C705[0D6F0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4855 00004382 0000                <1>
  4856 00004384 E94BF7FFFF          <1> 	jmp	error	
  4857                              <1> 
  4858                              <1> ; Original UNIX v1 'sysgtty' routine:
  4859                              <1> ; sysgtty:
  4860                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4861                              <1> 	;	       / r2 has destination
  4862                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4863                              <1> 	;                     / in 1st word of dest
  4864                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4865                              <1> 	;                     / in 2nd word of dest
  4866                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4867                              <1>         ;jmp    sysret2 / return to user
  4868                              <1> 	
  4869                              <1> ; Original UNIX v1 'gtty' routine:
  4870                              <1> ; gtty:
  4871                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4872                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4873                              <1>         ;jsr    r0,getf / get the i-number of the file
  4874                              <1>         ;tst    r1 / is it open for reading
  4875                              <1>         ;bgt    1f / yes
  4876                              <1>         ;neg    r1 / no, i-number is negative, 
  4877                              <1> 	;          / so make it positive
  4878                              <1> ;1:
  4879                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4880                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4881                              <1>         ;bhis   error9 / no, error
  4882                              <1>         ;asl    r1 / 0%2
  4883                              <1>         ;asl    r1 / 0%4 / yes
  4884                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4885                              <1> 	;	       ; / tty block
  4886                              <1>         ;mov    u.off,r2 / put argument in r2
  4887                              <1>         ;rts    r0 / return
  2089                                  %include 'u2.s'        ; 11/05/2015
  2090                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS2.INC
  2091                              <1> ; Last Modification: 11/02/2022
  2092                              <1> ; ----------------------------------------------------------------------------
  2093                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2094                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2095                              <1> ;
  2096                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2097                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2098                              <1> ; <Bell Laboratories (17/3/1972)>
  2099                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2100                              <1> ;
  2101                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2102                              <1> ;
  2103                              <1> ; ****************************************************************************
  2104                              <1> 
  2105                              <1> syslink:
  2106                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2107                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2108                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2109                              <1> 	;
  2110                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2111                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2112                              <1> 	; given to the entry that will go in the current directory.
  2113                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2114                              <1> 	; in the name 2 entry of current directory is the same
  2115                              <1> 	; i-number for the name 1 file.
  2116                              <1> 	;
  2117                              <1> 	; Calling sequence:
  2118                              <1> 	;	syslink; name 1; name 2
  2119                              <1> 	; Arguments:
  2120                              <1> 	;	name 1 - file name to which link will be created.
  2121                              <1> 	;	name 2 - name of entry in current directory that
  2122                              <1> 	;		 links to name 1.
  2123                              <1> 	; Inputs: -
  2124                              <1> 	; Outputs: -
  2125                              <1> 	; ...............................................................
  2126                              <1> 	;	
  2127                              <1> 	; Retro UNIX 8086 v1 modification: 
  2128                              <1> 	;       'syslink' system call has two arguments; so,
  2129                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2130                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2131                              <1> 	;
  2132                              <1> 		; / name1, name2
  2133                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2134 00004389 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  2135 0000438F 51                  <1> 	push	ecx
  2136 00004390 E83D060000          <1> 	call	namei
  2137                              <1> 		; jsr r0,namei / find the i-number associated with
  2138                              <1> 			     ; / the 1st path name
  2139                              <1>      	;;and	ax, ax
  2140                              <1> 	;;jz	error ; File not found
  2141                              <1> 	;jc	error 
  2142                              <1> 		; br error9 / cannot be found
  2143 00004395 730F                <1> 	jnc	short syslink0
  2144                              <1> 	;pop 	ecx
  2145                              <1> 	; 'file not found !' error
  2146 00004397 C705[0D6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2146 0000439F 0000                <1>
  2147 000043A1 E92EF7FFFF          <1> 	jmp	error
  2148                              <1> syslink0:
  2149 000043A6 E8EC0D0000          <1> 	call	iget
  2150                              <1> 		; jsr r0,iget / get the i-node into core
  2151 000043AB 8F05[D06E0000]      <1> 	pop	dword [u.namep] ; ecx
  2152                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2153                              <1> 	; 24/12/2021
  2154 000043B1 50                  <1> 	push	eax ; *
  2155                              <1> 	;push	ax
  2156                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2157                              <1> 			    ; / (a link to this file is to be created)
  2158                              <1> 	; 24/12/2021
  2159 000043B2 8A0D[9F6E0000]      <1> 	mov	cl, [cdev]
  2160 000043B8 51                  <1> 	push	ecx ; **
  2161                              <1> 	;push	word [cdev]
  2162                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2163 000043B9 E852000000          <1> 	call	isdir
  2164                              <1> 		; jsr r0,isdir / is it a directory
  2165 000043BE E80F060000          <1> 	call	namei
  2166                              <1> 		; jsr r0,namei / no, get i-number of name2
  2167                              <1> 	;jnc	error
  2168                              <1> 		; br .+4   / not found 
  2169                              <1> 			 ; / so r1 = i-number of current directory
  2170                              <1> 			 ; / ii = i-number of current directory
  2171                              <1> 		; br error9 / file already exists., error
  2172 000043C3 720F                <1> 	jc	short syslink1
  2173                              <1> 	; pop eax ; 24/12/2021
  2174                              <1> 	; pop eax
  2175                              <1> 	; 'file exists !' error
  2176 000043C5 C705[0D6F0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2176 000043CD 0000                <1>
  2177 000043CF E900F7FFFF          <1> 	jmp	error
  2178                              <1> syslink1:
  2179                              <1> 	;pop	cx
  2180                              <1> 	; 24/12/2021
  2181 000043D4 59                  <1> 	pop	ecx ; **
  2182                              <1> 	;cmp	cx, [cdev]
  2183 000043D5 3A0D[9F6E0000]      <1> 	cmp	cl, [cdev]
  2184                              <1> 	;jne	error
  2185                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2186                              <1> 			       ; / end of current directory
  2187                              <1> 	        ; bne error9
  2188 000043DB 740F                <1> 	je	short syslink2
  2189                              <1> 	; 'not same drive !' error
  2190 000043DD C705[0D6F0000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2190 000043E5 0000                <1>
  2191 000043E7 E9E8F6FFFF          <1> 	jmp	error
  2192                              <1> syslink2:
  2193                              <1> 	;pop	eax ; 24/12/2021
  2194                              <1> 	;push	eax
  2195                              <1> 	; 24/12/2021
  2196 000043EC 8B0424              <1> 	mov	eax, [esp] ; *
  2197 000043EF 66A3[EA6E0000]      <1> 	mov	[u.dirbuf], ax
  2198                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2199 000043F5 E89E000000          <1> 	call	mkdir
  2200                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2201                              <1> 		 	     ; / in current directory
  2202                              <1> 	; 24/12/2021
  2203 000043FA 58                  <1> 	pop	eax ; *
  2204                              <1> 	;pop	ax
  2205                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2206 000043FB E8970D0000          <1> 	call	iget
  2207                              <1> 		; jsr r0,iget / get i-node into core
  2208 00004400 FE05[BA6B0000]      <1> 	inc	byte [i.nlks]
  2209                              <1> 		; incb i.nlks / add 1 to its number of links
  2210 00004406 E8960E0000          <1> 	call	setimod
  2211                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2212 0000440B E9E4F6FFFF          <1> 	jmp	sysret
  2213                              <1> 
  2214                              <1> isdir:
  2215                              <1> 	; 03/02/2022
  2216                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2217                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2218                              <1> 	;
  2219                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2220                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2221                              <1> 	;  called by syslink and sysunlink to make sure directories
  2222                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2223                              <1> 	; 'isdir' does not bother checking. The current i-node
  2224                              <1> 	;  is not disturbed.			
  2225                              <1> 	;		
  2226                              <1> 	; INPUTS ->
  2227                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2228                              <1> 	;    u.uid - user id
  2229                              <1> 	; OUTPUTS ->
  2230                              <1> 	;    r1 - contains current i-number upon exit
  2231                              <1> 	;    	 (current i-node back in core) 
  2232                              <1> 	;	
  2233                              <1> 	; ((AX = R1))
  2234                              <1> 	;
  2235                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2236                              <1> 	;
  2237                              <1> 
  2238                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2239                              <1> 	; / there is an error unless super user made the call
  2240                              <1> 	
  2241 00004410 803D[046F0000]00    <1> 	cmp	byte [u.uid], 0 
  2242                              <1> 		; tstb u.uid / super user
  2243 00004417 762B                <1> 	jna	short isdir1
  2244                              <1> 		; beq 1f / yes, don't care
  2245 00004419 66FF35[9C6E0000]    <1> 	push	word [ii]
  2246                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2247 00004420 E8720D0000          <1> 	call	iget
  2248                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2249                              <1> 	; 03/02/2022
  2250 00004425 F605[B96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2251                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2252                              <1> 		; bit $40000,i.flgs / is it a directory
  2253                              <1> 	;jnz	error
  2254                              <1> 		; bne error9 / yes, error
  2255 0000442C 740F                <1> 	jz	short isdir0
  2256 0000442E C705[0D6F0000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2256 00004436 0000                <1>
  2257                              <1> 				; 'permission denied !' error
  2258                              <1> 	; pop	ax
  2259 00004438 E997F6FFFF          <1> 	jmp	error	
  2260                              <1> isdir0:	
  2261 0000443D 6658                <1> 	pop	ax
  2262                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2263 0000443F E8530D0000          <1> 	call	iget
  2264                              <1> 		; jsr r0,iget / get it back in
  2265                              <1> isdir1: ; 1:
  2266 00004444 C3                  <1> 	retn
  2267                              <1> 		; rts r0
  2268                              <1> 
  2269                              <1> sysunlink:
  2270                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2271                              <1> 	; 04/12/2015 (14 byte file names)
  2272                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2273                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2274                              <1> 	;
  2275                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2276                              <1> 	; name from its directory. If this entry was the last link
  2277                              <1> 	; to the file, the contents of the file are freed and the
  2278                              <1> 	; file is destroyed. If, however, the file was open in any
  2279                              <1> 	; process, the actual destruction is delayed until it is 
  2280                              <1> 	; closed, even though the directory entry has disappeared.
  2281                              <1> 	; 
  2282                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2283                              <1> 	; does not exist or that its directory can not be written.
  2284                              <1> 	; Write permission is not required on the file itself.
  2285                              <1> 	; It is also illegal to unlink a directory (except for
  2286                              <1> 	; the superuser).
  2287                              <1> 	;
  2288                              <1> 	; Calling sequence:
  2289                              <1> 	;	sysunlink; name
  2290                              <1> 	; Arguments:
  2291                              <1> 	;	name - name of directory entry to be removed 
  2292                              <1> 	; Inputs: -
  2293                              <1> 	; Outputs: -
  2294                              <1> 	; ...............................................................
  2295                              <1> 	;				
  2296                              <1> 	; Retro UNIX 8086 v1 modification:
  2297                              <1> 	;	 The user/application program puts address of the name
  2298                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2299                              <1> 
  2300                              <1> 	; / name - remove link name
  2301 00004445 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  2302                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2303 0000444B E882050000          <1> 	call	namei
  2304                              <1> 		; jsr r0,namei / find the i-number associated 
  2305                              <1> 			     ; / with the path name
  2306                              <1> 	;jc	error
  2307                              <1> 		; br error9 / not found
  2308 00004450 730F                <1> 	jnc	short sysunlink1
  2309                              <1> 	; 'file not found !' error
  2310 00004452 C705[0D6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2310 0000445A 0000                <1>
  2311 0000445C E973F6FFFF          <1> 	jmp	error
  2312                              <1> sysunlink1:
  2313 00004461 50                  <1> 	push	eax ; 24/12/2021
  2314                              <1> 	;push	ax
  2315                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2316 00004462 E8A9FFFFFF          <1> 	call	isdir
  2317                              <1> 		; jsr r0,isdir / is it a directory
  2318                              <1> 	;xor 	ax, ax
  2319                              <1> 	; 24/12/2021
  2320 00004467 31C0                <1> 	xor	eax, eax
  2321 00004469 66A3[EA6E0000]      <1> 	mov	[u.dirbuf], ax ; 0
  2322                              <1> 		; clr u.dirbuf / no, clear the location that will
  2323                              <1> 			   ; / get written into the i-number portion
  2324                              <1> 			 ; / of the entry
  2325 0000446F 832D[D46E0000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2326                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2327 00004476 E868000000          <1> 	call	wdir
  2328                              <1> 		; jsr r0,wdir / free the directory entry
  2329 0000447B 58                  <1> 	pop	eax ; 24/12/2021
  2330                              <1> 	;pop	ax
  2331                              <1> 		; mov (sp)+,r1 / get i-number back
  2332 0000447C E8160D0000          <1> 	call	iget
  2333                              <1> 		; jsr r0,iget / get i-node
  2334 00004481 E81B0E0000          <1> 	call	setimod
  2335                              <1> 		; jsr r0,setimod / set modified flag
  2336 00004486 FE0D[BA6B0000]      <1> 	dec	byte [i.nlks]
  2337                              <1> 		; decb i.nlks / decrement the number of links
  2338                              <1> 	; 24/12/2021
  2339 0000448C 7505                <1> 	jnz	short sysunlink_2
  2340                              <1> 	;jnz	sysret
  2341                              <1> 		; bgt sysret9 / if this was not the last link
  2342                              <1> 			    ; / to file return
  2343                              <1> 	; AX = r1 = i-number
  2344 0000448E E85B090000          <1> 	call	anyi
  2345                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2346                              <1> 			 ; / Then free contents of file and destroy it.
  2347                              <1> sysunlink_2:
  2348 00004493 E95CF6FFFF          <1> 	jmp	sysret
  2349                              <1> 		; br sysret9
  2350                              <1> 
  2351                              <1> mkdir:
  2352                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2353                              <1> 	; 04/12/2015 (14 byte directory names)
  2354                              <1> 	; 12/10/2015
  2355                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2356                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2357                              <1> 	;
  2358                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2359                              <1> 	; by u.namep into the current directory.
  2360                              <1> 	;
  2361                              <1> 	; INPUTS ->
  2362                              <1> 	;    u.namep - points to a file name 
  2363                              <1> 	;	           that is about to be a directory entry.
  2364                              <1> 	;    ii - current directory's i-number.	
  2365                              <1> 	; OUTPUTS ->
  2366                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2367                              <1> 	;    u.off - points to entry to be filled 
  2368                              <1> 	;	     in the current directory		
  2369                              <1> 	;    u.base - points to start of u.dirbuf.
  2370                              <1> 	;    r1 - contains i-number of current directory 
  2371                              <1> 	;	
  2372                              <1> 	; ((AX = R1)) output
  2373                              <1> 	;
  2374                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2375                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2376                              <1> 	;
  2377                              <1> 
  2378                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2379 00004498 31C0                <1> 	xor 	eax, eax
  2380 0000449A BF[EC6E0000]        <1> 	mov     edi, u.dirbuf+2
  2381 0000449F 89FE                <1> 	mov	esi, edi
  2382 000044A1 AB                  <1> 	stosd
  2383 000044A2 AB                  <1> 	stosd
  2384                              <1> 	; 04/12/2015 (14 byte directory names)
  2385 000044A3 AB                  <1> 	stosd
  2386 000044A4 66AB                <1> 	stosw
  2387                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2388 000044A6 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2389                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2390                              <1> 	;mov 	ebp, [u.namep]
  2391 000044A8 E85E060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2392                              <1> 		; esi = physical address (page start + offset)
  2393                              <1> 		; ecx = byte count in the page (1 - 4096)
  2394                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2395                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2396                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2397                              <1> mkdir_1: ; 1: 
  2398 000044AD 45                  <1> 	inc	ebp ; 12/10/2015
  2399                              <1> 	;
  2400                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2401                              <1> 	 ; 01/08/2013
  2402 000044AE AC                  <1> 	lodsb
  2403                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2404 000044AF 20C0                <1> 	and 	al, al
  2405 000044B1 7426                <1> 	jz 	short mkdir_3 	  
  2406                              <1> 		; beq 1f / if null, done
  2407 000044B3 3C2F                <1> 	cmp	al, '/'
  2408                              <1> 		; cmp r1,$'/ / is it a "/"?
  2409 000044B5 7413                <1> 	je	short mkdir_err
  2410                              <1> 	;je	error
  2411                              <1> 		; beq error9 / yes, error
  2412                              <1> 	; 12/10/2015
  2413                              <1> 	;dec	cx
  2414 000044B7 49                  <1> 	dec	ecx ; 24/12/2021
  2415 000044B8 7505                <1> 	jnz	short mkdir_2
  2416                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2417 000044BA E852060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2418                              <1> 		; esi = physical address (page start + offset)
  2419                              <1> 		; ecx = byte count in the page
  2420                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2421                              <1> mkdir_2:
  2422 000044BF 81FF[FA6E0000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2423                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2424                              <1> 				     ; / a char?
  2425 000044C5 74E6                <1> 	je	short mkdir_1
  2426                              <1> 		; beq 1b / yes, go back
  2427 000044C7 AA                  <1> 	stosb
  2428                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2429 000044C8 EBE3                <1> 	jmp 	short mkdir_1
  2430                              <1> 		; br 1b / get next char
  2431                              <1> mkdir_err:
  2432                              <1> 	; 17/06/2015
  2433 000044CA C705[0D6F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2433 000044D2 0000                <1>
  2434 000044D4 E9FBF5FFFF          <1> 	jmp	error
  2435                              <1> 
  2436                              <1> mkdir_3: ; 1:
  2437 000044D9 A1[CC6E0000]        <1> 	mov	eax, [u.dirp]
  2438 000044DE A3[D46E0000]        <1> 	mov	[u.off], eax
  2439                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2440                              <1> 				 ; / slot to u.off
  2441                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2442                              <1> 	; 29/04/2013
  2443 000044E3 C705[D86E0000]-     <1>         mov     dword [u.base], u.dirbuf
  2443 000044E9 [EA6E0000]          <1>
  2444                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2445 000044ED C705[DC6E0000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2445 000044F5 0000                <1>
  2446                              <1> 		; mov $10.,u.count / u.count = 10
  2447 000044F7 66A1[9C6E0000]      <1> 	mov	ax, [ii] 
  2448                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2449 000044FD B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2450 000044FF E8670D0000          <1> 	call 	access
  2451                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2452                              <1> 				 ; / for writing
  2453                              <1> 	; AX = i-number of current directory
  2454                              <1> 	; 01/08/2013
  2455 00004504 FE05[1F6F0000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2456                              <1> 	;call	writei
  2457                              <1> 	;	; jsr r0,writei / write into directory
  2458                              <1> 	;retn	
  2459                              <1> 	;	; rts r0
  2460                              <1> 	; 24/12/2021
  2461 0000450A E94A100000          <1> 	jmp	writei
  2462                              <1> 
  2463                              <1> sysexec:
  2464                              <1> 	; 03/02/2022
  2465                              <1> 	; 12/01/2022
  2466                              <1> 	; 08/01/2022
  2467                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2468                              <1> 	; 23/10/2015
  2469                              <1> 	; 19/10/2015
  2470                              <1> 	; 10/10/2015, 18/10/2015
  2471                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2472                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2473                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2474                              <1> 	; 24/06/2015, 25/06/2015
  2475                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2476                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2477                              <1> 	;
  2478                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2479                              <1> 	; pointed to by 'name' in the sysexec call. 
  2480                              <1> 	; 'sysexec' performs the following operations:
  2481                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2482                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2483                              <1> 	;    3. sets trap vectors to system routines.
  2484                              <1> 	;    4. loads arguments to be passed to executing file into
  2485                              <1> 	;	highest locations of user's core
  2486                              <1> 	;    5. puts pointers to arguments in locations immediately
  2487                              <1> 	;	following arguments.
  2488                              <1> 	;    6.	saves number of arguments in next location.
  2489                              <1> 	;    7. initializes user's stack area so that all registers
  2490                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2491                              <1> 	;	to core when 'sysret' restores registers 
  2492                              <1> 	;	and does an rti.
  2493                              <1> 	;    8. inializes u.r0 and u.sp
  2494                              <1> 	;    9. zeros user's core down to u.r0
  2495                              <1> 	;   10.	reads executable file from storage device into core
  2496                              <1> 	;	starting at location 'core'.
  2497                              <1> 	;   11.	sets u.break to point to end of user's code with
  2498                              <1> 	;	data area appended.
  2499                              <1> 	;   12.	calls 'sysret' which returns control at location
  2500                              <1> 	;	'core' via 'rti' instruction. 		  		
  2501                              <1> 	;
  2502                              <1> 	; Calling sequence:
  2503                              <1> 	;	sysexec; namep; argp
  2504                              <1> 	; Arguments:
  2505                              <1> 	;	namep - points to pathname of file to be executed
  2506                              <1> 	;	argp  - address of table of argument pointers
  2507                              <1> 	;	argp1... argpn - table of argument pointers
  2508                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2509                              <1> 	; Inputs: (arguments)
  2510                              <1> 	; Outputs: -	
  2511                              <1> 	; ...............................................................
  2512                              <1> 	;
  2513                              <1> 	; Retro UNIX 386 v1 modification: 
  2514                              <1> 	;	User application runs in it's own virtual space 
  2515                              <1> 	;	which is izolated from kernel memory (and other
  2516                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2517                              <1> 	;	privilige mode. Virtual start address is always 0.
  2518                              <1> 	;	User's core memory starts at linear address 400000h
  2519                              <1> 	;	(the end of the 1st 4MB).
  2520                              <1> 	;
  2521                              <1> 	; Retro UNIX 8086 v1 modification: 
  2522                              <1> 	;	user/application segment and system/kernel segment
  2523                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2524                              <1> 	;	are different (user's registers are saved to 
  2525                              <1> 	;	and then restored from system's stack.)
  2526                              <1> 	;
  2527                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2528                              <1> 	;	      arguments which were in these registers;
  2529                              <1> 	;	      but, it returns by putting the 1st argument
  2530                              <1> 	;	      in 'u.namep' and the 2nd argument
  2531                              <1> 	;	      on top of stack. (1st argument is offset of the
  2532                              <1> 	;	      file/path name in the user's program segment.)		 	
  2533                              <1> 	
  2534                              <1> 	;call	arg2
  2535                              <1> 	; * name - 'u.namep' points to address of file/path name
  2536                              <1> 	;          in the user's program segment ('u.segmnt')
  2537                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2538                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2539                              <1> 	;          which is on top of stack.
  2540                              <1> 	;
  2541                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2542                              <1> 
  2543                              <1> 	; 23/06/2015 (32 bit modifications)
  2544                              <1> 
  2545 0000450F 891D[D06E0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2546                              <1>         ; 18/10/2015
  2547 00004515 890D[386F0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2548 0000451B E8B2040000          <1> 	call	namei
  2549                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2550                              <1> 			     ; / named in sysexec call in r1
  2551                              <1> 	;jc	error
  2552                              <1> 		; br error9
  2553 00004520 731E                <1> 	jnc	short sysexec_0
  2554                              <1> 	;
  2555                              <1> 	; 'file not found !' error
  2556 00004522 C705[0D6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2556 0000452A 0000                <1>
  2557 0000452C E9A3F5FFFF          <1> 	jmp	error 
  2558                              <1> sysexec_not_exf:
  2559                              <1> 	; 'not executable file !' error
  2560 00004531 C705[0D6F0000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2560 00004539 0000                <1>
  2561 0000453B E994F5FFFF          <1> 	jmp	error 
  2562                              <1> sysexec_0:
  2563 00004540 E8520C0000          <1> 	call	iget
  2564                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2565                              <1> 	; 24/12/2021
  2566 00004545 F605[B86B0000]10    <1> 	test	byte [i.flgs], 10h
  2567                              <1> 	;test	word [i.flgs], 10h
  2568                              <1> 	;	; bit $20,i.flgs / is file executable
  2569 0000454C 74E3                <1> 	jz	short sysexec_not_exf
  2570                              <1> 	;jz	error
  2571                              <1> 		; beq error9
  2572                              <1> 	;;
  2573 0000454E E8C8130000          <1> 	call	iopen
  2574                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2575                              <1> 			     ; / given in r1 (opens file)
  2576                              <1> 	; AX = i-number of the file
  2577                              <1> 	; 24/12/2021
  2578 00004553 F605[B86B0000]20    <1> 	test	byte [i.flgs], 20h
  2579                              <1> 	;test	word [i.flgs], 20h
  2580                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2581 0000455A 7415                <1> 	jz	short sysexec_1
  2582                              <1> 		; beq 1f
  2583 0000455C 803D[046F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2584                              <1> 		; tstb u.uid / test user id
  2585 00004563 760C                <1> 	jna	short sysexec_1
  2586                              <1> 		; beq 1f / super user
  2587 00004565 8A0D[BB6B0000]      <1> 	mov	cl, [i.uid]
  2588 0000456B 880D[046F0000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2589                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2590                              <1> 				 ; / as process user id
  2591                              <1> sysexec_1:
  2592                              <1> 	; 03/02/2022
  2593                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2594                              <1> 	; 18/10/2215
  2595                              <1> 	; 10/10/2015
  2596                              <1> 	; 21/07/2015, 24/07/2015
  2597                              <1> 	; 24/06/2015, 25/06/2015
  2598                              <1>         ; Moving arguments to the end of [u.upage]
  2599                              <1> 	; (by regarding page borders in user's memory space)
  2600                              <1> 	;
  2601                              <1> 	; 10/10/2015
  2602                              <1> 	; 21/07/2015
  2603 00004571 89E5                <1> 	mov	ebp, esp ; (**)
  2604                              <1> 	; 18/10/2015
  2605 00004573 89EF                <1> 	mov 	edi, ebp
  2606 00004575 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2607                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2608 0000457A 29CF                <1> 	sub	edi, ecx
  2609 0000457C 89FC                <1> 	mov	esp, edi
  2610 0000457E 31C0                <1> 	xor	eax, eax
  2611 00004580 A3[E06E0000]        <1> 	mov 	[u.nread], eax ; 0
  2612                              <1> 	; 12/01/2022
  2613                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2614                              <1> 	; may leave it with any value after an error))
  2615                              <1> 	;mov	[argc], ax
  2616 00004585 A2[366F0000]        <1> 	mov	[argc], al ; 0
  2617                              <1> 	;
  2618 0000458A 49                  <1> 	dec	ecx ; 256 - 1
  2619 0000458B 890D[DC6E0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2620                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2621                              <1> sysexec_2:
  2622 00004591 8B35[386F0000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2623 00004597 E860020000          <1> 	call	get_argp
  2624                              <1> 	;mov	ecx, 4 
  2625                              <1> 	; 03/02/2022
  2626 0000459C 31C9                <1> 	xor	ecx, ecx
  2627 0000459E B104                <1> 	mov	cl, 4
  2628                              <1> sysexec_3:
  2629 000045A0 21C0                <1> 	and	eax, eax
  2630 000045A2 7455                <1> 	jz	short sysexec_6
  2631                              <1> 	; 18/10/2015
  2632 000045A4 010D[386F0000]      <1> 	add	[argv], ecx ; 4
  2633                              <1> 	;inc	word [argc]
  2634                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2635 000045AA FE05[366F0000]      <1> 	inc	byte [argc]
  2636                              <1> 	;
  2637 000045B0 A3[D86E0000]        <1> 	mov	[u.base], eax
  2638                              <1>  	; 23/10/2015
  2639 000045B5 66C705[1D6F0000]00- <1> 	mov	word [u.pcount], 0
  2639 000045BD 00                  <1>
  2640                              <1> sysexec_4:
  2641 000045BE E84B110000          <1> 	call	cpass ; get a character from user's core memory
  2642 000045C3 750B                <1>         jnz	short sysexec_5
  2643                              <1> 		; (max. 255 chars + null)
  2644                              <1> 	; 18/10/2015
  2645 000045C5 28C0                <1> 	sub 	al, al
  2646 000045C7 AA                  <1> 	stosb
  2647 000045C8 FF05[E06E0000]      <1> 	inc	dword [u.nread]
  2648 000045CE EB29                <1> 	jmp	short sysexec_6
  2649                              <1> sysexec_5:
  2650 000045D0 AA                  <1> 	stosb
  2651 000045D1 20C0                <1> 	and 	al, al
  2652 000045D3 75E9                <1> 	jnz	short sysexec_4
  2653                              <1> 	;mov	ecx, 4
  2654                              <1> 	; 24/12/2021
  2655 000045D5 29C9                <1> 	sub	ecx, ecx
  2656 000045D7 B104                <1> 	mov	cl, 4
  2657                              <1> 	;cmp	[ncount], ecx ; 4
  2658                              <1> 	; 24/12/2021
  2659 000045D9 66390D[346F0000]    <1> 	cmp	[ncount], cx ; 4
  2660 000045E0 72AF                <1> 	jb	short sysexec_2
  2661 000045E2 8B35[306F0000]      <1> 	mov	esi, [nbase]
  2662 000045E8 010D[306F0000]      <1> 	add	[nbase], ecx ; 4	
  2663 000045EE 66290D[346F0000]    <1> 	sub	[ncount], cx 
  2664 000045F5 8B06                <1> 	mov	eax, [esi]
  2665 000045F7 EBA7                <1> 	jmp	short sysexec_3
  2666                              <1> sysexec_6:
  2667                              <1> 	; 18/10/2015
  2668                              <1> 	; argument list transfer from user's core memory to
  2669                              <1> 	; kernel stack frame is OK here.
  2670                              <1> 	; [u.nread] = ; argument list length
  2671                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2672                              <1> 	;
  2673                              <1> 	; 18/10/2015
  2674                              <1> 	; 24/07/2015
  2675                              <1>         ; 21/07/2015
  2676                              <1> 	; 02/07/2015
  2677                              <1> 	; 25/06/2015
  2678                              <1> 	; 24/06/2015
  2679                              <1> 	; 23/06/2015
  2680                              <1> 	;
  2681 000045F9 8B1D[156F0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2682 000045FF 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2683 00004601 740A                <1> 	jz	short sysexec_7
  2684 00004603 A1[116F0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2685 00004608 E8DBE8FFFF          <1> 	call	deallocate_page_dir
  2686                              <1> sysexec_7:
  2687 0000460D E80BE8FFFF          <1> 	call	make_page_dir
  2688                              <1> 	;jc	short sysexec_14
  2689                              <1> 	;jc	panic  ; allocation error 
  2690                              <1> 		       ; after a deallocation would be nonsence !?
  2691                              <1> 	; 08/01/2022
  2692 00004612 7243                <1> 	jc	short sysexec_panic
  2693                              <1> 
  2694                              <1> 	; 24/07/2015
  2695                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2696                              <1> 	;     of the user's page directory
  2697                              <1> 	;     (It is needed for interrupts!)
  2698                              <1> 	; 18/10/2015
  2699 00004614 8B15[F86A0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2700 0000461A 8B02                <1> 	mov	eax, [edx] ; physical address of
  2701                              <1> 			   ; kernel's first page table (1st 4 MB)
  2702                              <1> 			   ; (PDE 0 of kernel's page directory)
  2703 0000461C 8B15[116F0000]      <1> 	mov 	edx, [u.pgdir]
  2704 00004622 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2705                              <1> 	;
  2706                              <1> 	; 20/07/2015
  2707 00004624 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2708                              <1> 	; 18/10/2015
  2709 00004629 BE[286F0000]        <1> 	mov	esi, pcore ; physical start address
  2710                              <1> sysexec_8:	
  2711 0000462E B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2712 00004633 E803E8FFFF          <1> 	call	make_page_table
  2713                              <1> 	;jc	panic
  2714                              <1> 	; 24/12/2021
  2715 00004638 721D                <1> 	jc	short sysexec_panic
  2716                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2717 0000463A E80AE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2718                              <1> 	;jc	panic
  2719                              <1> 	; 24/12/2021
  2720 0000463F 7216                <1> 	jc	short sysexec_panic
  2721                              <1> 	;
  2722 00004641 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2723                              <1> 	; ebx = virtual address (24/07/2015)
  2724                              <1> 	; 24/12/2021
  2725                              <1> 	;call 	add_to_swap_queue
  2726                              <1> 	; 18/10/2015
  2727 00004643 81FE[2C6F0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2728 00004649 7411                <1> 	je	short sysexec_9 ; yes
  2729 0000464B BE[2C6F0000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2730                              <1> 	; 20/07/2015
  2731 00004650 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2732                              <1> 	; ebx = virtual end address + segment base address - 4K
  2733 00004655 EBD7                <1>         jmp     short sysexec_8
  2734                              <1> 
  2735                              <1> sysexec_panic:
  2736                              <1> 	; 26/03/2021
  2737 00004657 E92CEDFFFF          <1> 	jmp	panic
  2738                              <1> 
  2739                              <1> sysexec_9:
  2740                              <1> 	; 18/10/2015
  2741                              <1> 	; 26/08/2015
  2742                              <1> 	; 25/06/2015
  2743                              <1> 	; move arguments from kernel stack to [ecore]
  2744                              <1> 	; (argument list/line will be copied from kernel stack
  2745                              <1> 	; frame to the last (stack) page of user's core memory)
  2746                              <1> 	; 18/10/2015
  2747 0000465C 8B3D[2C6F0000]      <1> 	mov	edi, [ecore]
  2748 00004662 81C700100000        <1> 	add	edi, PAGE_SIZE
  2749                              <1> 	;movzx	eax, word [argc]
  2750                              <1> 	; 12/01/2022
  2751 00004668 31C0                <1> 	xor	eax, eax
  2752 0000466A A0[366F0000]        <1> 	mov	al, [argc]
  2753 0000466F 08C0                <1> 	or	al, al
  2754                              <1> 	;or	eax, eax
  2755 00004671 7509                <1> 	jnz	short sysexec_10
  2756 00004673 89FB                <1> 	mov 	ebx, edi
  2757 00004675 83EB04              <1> 	sub	ebx, 4 
  2758 00004678 8903                <1> 	mov	[ebx], eax ; 0
  2759 0000467A EB40                <1> 	jmp 	short sysexec_13
  2760                              <1> sysexec_10:
  2761 0000467C 8B0D[E06E0000]      <1> 	mov	ecx, [u.nread]
  2762                              <1> 	;mov 	esi, [argv]
  2763 00004682 89E6                <1> 	mov	esi, esp ; start address of argument list
  2764 00004684 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2765 00004686 89C2                <1> 	mov	edx, eax
  2766                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2767 00004688 FEC2                <1> 	inc	dl ; argument count + 1 for argc value  
  2768 0000468A C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2769                              <1> 	; edx <= 128
  2770 0000468D 89FB                <1> 	mov	ebx, edi
  2771 0000468F 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2772 00004692 29D3                <1> 	sub 	ebx, edx
  2773 00004694 89FA                <1> 	mov	edx, edi
  2774 00004696 F3A4                <1> 	rep	movsb
  2775 00004698 89D6                <1> 	mov 	esi, edx
  2776 0000469A 89DF                <1> 	mov 	edi, ebx
  2777 0000469C BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2778 000046A1 2B15[2C6F0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2779 000046A7 AB                  <1> 	stosd	; eax = argument count	
  2780                              <1> sysexec_11:
  2781 000046A8 89F0                <1> 	mov	eax, esi
  2782 000046AA 01D0                <1> 	add	eax, edx
  2783 000046AC AB                  <1> 	stosd  ; eax = virtual address
  2784 000046AD FE0D[366F0000]      <1> 	dec	byte [argc]
  2785 000046B3 7407                <1> 	jz	short sysexec_13
  2786                              <1> sysexec_12:
  2787 000046B5 AC                  <1> 	lodsb
  2788 000046B6 20C0                <1> 	and	al, al
  2789 000046B8 75FB                <1> 	jnz	short sysexec_12
  2790 000046BA EBEC                <1> 	jmp	short sysexec_11
  2791                              <1> 	;
  2792                              <1> 	; 1:
  2793                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2794                              <1> 			     ; / pointers to arguments to be passed
  2795                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2796                              <1> 			      ; / u.quit = 1 take quit
  2797                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2798                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2799                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2800                              <1> 			       ; / system routine
  2801                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2802                              <1> 			       ; / set to take system routine
  2803                              <1> 		; mov $sstack,sp / stack space used during swapping
  2804                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2805                              <1> 		; mov $ecore,r5 / r5 has end of core
  2806                              <1> 		; mov $core,r4 / r4 has start of users core
  2807                              <1> 		; mov r4,u.base / u.base has start of users core
  2808                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2809                              <1> 	; 1:
  2810                              <1> 		; tst (r2)+ / argument char = "nul"
  2811                              <1> 		; bne 1b
  2812                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2813                              <1> 			  ; / end of argument pointer list
  2814                              <1> 	; 1:
  2815                              <1> 	     ; / move arguments to bottom of users core
  2816                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2817                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2818                              <1> 			    ; / ptr list
  2819                              <1> 		; blo 1f / branch to 1f when all arguments
  2820                              <1> 		       ; / are moved
  2821                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2822                              <1> 	; 2:
  2823                              <1> 		; tstb (r3)+
  2824                              <1> 		; bne 2b / scan argument for \0 (nul)
  2825                              <1> 
  2826                              <1> 	; 2:
  2827                              <1> 		; movb -(r3),-(r5) / move argument char 
  2828                              <1> 				 ; / by char starting at "ecore"
  2829                              <1> 		; cmp r3,(r2) / moved all characters in 
  2830                              <1> 			    ; / this argument
  2831                              <1> 		; bhi 2b / branch 2b if not
  2832                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2833                              <1> 			     ; / r5 has pointer to nth arg
  2834                              <1> 		; br 1b / string
  2835                              <1> 	; 1:
  2836                              <1> 		; clrb -(r5)
  2837                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2838                              <1> 			; / last word of argument strings
  2839                              <1> 		; mov $core,r2
  2840                              <1> 	
  2841                              <1> 	; 1: / move argument pointers into core following 
  2842                              <1> 	      ; / argument strings
  2843                              <1> 		; cmp r2,r4
  2844                              <1> 		; bhis 1f / branch to 1f when all pointers
  2845                              <1> 			; / are moved
  2846                              <1> 		; mov (r2)+,-(r5)
  2847                              <1> 		; br 1b
  2848                              <1> 	; 1:
  2849                              <1> 		; sub $core,r4 / gives number of arguments *2
  2850                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2851                              <1> 		       ; / the number of args stored
  2852                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2853                              <1> 			     ; / of the argument pointers
  2854                              <1> sysexec_13:
  2855                              <1> 	; 19/10/2015
  2856                              <1> 	; 18/10/2015
  2857                              <1> 	; 29/07/2015
  2858                              <1> 	; 25/07/2015
  2859                              <1> 	; 24/07/2015
  2860                              <1> 	; 20/07/2015
  2861                              <1> 	; 25/06/2015
  2862                              <1> 	; 24/06/2015
  2863                              <1> 	; 23/06/2015
  2864                              <1> 	;
  2865                              <1> 	; moving arguments to [ecore] is OK here..
  2866                              <1> 	; 18/10/2015
  2867 000046BC 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2868                              <1> 	; ebx = beginning addres of argument list pointers
  2869                              <1> 	;	in user's stack
  2870                              <1> 	; 19/10/2015
  2871 000046BE 2B1D[2C6F0000]      <1> 	sub 	ebx, [ecore]
  2872 000046C4 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2873                              <1> 			; end of core - 4096 (last page)
  2874                              <1> 			; (virtual address)
  2875 000046CA 891D[386F0000]      <1> 	mov	[argv], ebx
  2876 000046D0 891D[E46E0000]      <1> 	mov	[u.break], ebx ; available user memory
  2877                              <1> 	;
  2878 000046D6 29C0                <1> 	sub	eax, eax
  2879 000046D8 C705[DC6E0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2879 000046E0 0000                <1>
  2880                              <1> 		; mov $14,u.count
  2881 000046E2 C705[C86E0000]-     <1> 	mov	dword [u.fofp], u.off
  2881 000046E8 [D46E0000]          <1>
  2882                              <1> 		; mov $u.off,u.fofp
  2883 000046EC A3[D46E0000]        <1> 	mov	[u.off], eax ; 0
  2884                              <1> 		; clr u.off / set offset in file to be read to zero
  2885                              <1> 	; 25/07/2015
  2886 000046F1 A3[D86E0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2887                              <1> 	; 25/06/2015 
  2888 000046F6 66A1[9C6E0000]      <1> 	mov	ax, [ii]
  2889                              <1> 	; AX = i-number of the executable file
  2890 000046FC E86A0C0000          <1> 	call	readi
  2891                              <1> 		; jsr r0,readi / read in first six words of 
  2892                              <1> 			; / user's file, starting at $core
  2893                              <1> 		; mov sp,r5 / put users stack address in r5
  2894                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2895                              <1> 				; / from r5 (leaves number of words
  2896                              <1> 				; / less 26 available for
  2897                              <1> 			     	; / program in user core
  2898                              <1> 		; mov r5,u.count /
  2899                              <1> 	; 25/06/2015
  2900 00004701 8B0D[E46E0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2901 00004707 890D[DC6E0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2902                              <1> 	;
  2903 0000470D 8B0D[E06E0000]      <1> 	mov	ecx, [u.nread]
  2904 00004713 890D[E46E0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2905 00004719 80F920              <1> 	cmp	cl, 32
  2906 0000471C 7540                <1>         jne     short sysexec_15
  2907                              <1> 	;:
  2908                              <1> 	; 25/06/2015
  2909                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2910                              <1> 	; 18/10/2015
  2911 0000471E 8B35[286F0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2912                              <1> 		             ; (phys. start addr. of the exec. file)
  2913 00004724 AD                  <1> 	lodsd
  2914 00004725 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2915 00004729 7533                <1> 	jne	short sysexec_15
  2916                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2917                              <1> 			      ; / if file is standard a.out format
  2918                              <1> 		; bne 1f / branch, if not standard format
  2919 0000472B AD                  <1> 	lodsd
  2920 0000472C 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2921 0000472E AD                  <1> 	lodsd
  2922 0000472F 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2923                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2924                              <1> 		              ; / number of bytes in program text	
  2925                              <1> 		; sub $14,r5 / subtract 12
  2926 00004731 89CB                <1> 	mov	ebx, ecx
  2927                              <1> 	;
  2928                              <1> 	; 25/06/2015
  2929                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2930                              <1> 	;	and SINGLIX operating systems (as code template).
  2931                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2932                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2933                              <1> 	;	Overrun is not possible for current version. 	
  2934                              <1> 	;
  2935 00004733 AD                  <1> 	lodsd	
  2936 00004734 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2937 00004736 3B1D[DC6E0000]      <1> 	cmp	ebx, [u.count]
  2938 0000473C 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2939                              <1> 	;
  2940                              <1> 	; 24/07/2015
  2941                              <1> 	; add bss section size to [u.break]
  2942 0000473E 0105[E46E0000]      <1> 	add 	[u.break], eax
  2943                              <1> 	;
  2944 00004744 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2945                              <1> 	;cmp	ecx, [u.count]
  2946                              <1> 	;jnb	short sysexec_16
  2947                              <1> 		; cmp r5,u.count /
  2948                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2949 00004747 890D[DC6E0000]      <1> 	mov	[u.count], ecx ; required read count
  2950                              <1> 		; mov r5,u.count
  2951                              <1> 	;
  2952 0000474D EB2A                <1> 	jmp	short sysexec_16
  2953                              <1> 	;
  2954                              <1> sysexec_14:
  2955                              <1> 	; 23/06/2015
  2956                              <1> 	; insufficient (out of) memory
  2957 0000474F C705[0D6F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2957 00004757 0000                <1>
  2958 00004759 E976F3FFFF          <1> 	jmp	error
  2959                              <1> 	;
  2960                              <1> sysexec_15:
  2961                              <1> 	; 25/06/2015
  2962 0000475E 0FB715[BC6B0000]    <1>         movzx   edx, word [i.size] ; file size
  2963 00004765 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2964 00004767 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2965 00004769 01D1                <1> 	add	ecx, edx ; [i.size]
  2966 0000476B 3B0D[DC6E0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2967 00004771 77DC                <1> 	ja	short sysexec_14
  2968 00004773 8915[DC6E0000]      <1> 	mov	[u.count], edx
  2969                              <1> sysexec_16:
  2970 00004779 66A1[9C6E0000]      <1> 	mov	ax, [ii] ; i-number
  2971 0000477F E8E70B0000          <1> 	call	readi
  2972                              <1> 		; add core+10,u.nread / add size of user data area 
  2973                              <1> 		                    ; / to u.nread
  2974                              <1> 		; br 2f
  2975                              <1> 	; 1:
  2976                              <1> 		; jsr r0,readi / read in rest of file
  2977                              <1> 	; 2:
  2978 00004784 8B0D[E06E0000]      <1> 	mov	ecx, [u.nread]
  2979 0000478A 010D[E46E0000]      <1> 	add	[u.break], ecx
  2980                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2981                              <1> 				    ; / user code
  2982                              <1> 		; add $core+14,u.break / plus data area
  2983                              <1> sysexec_17: ; 20/07/2015
  2984                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2985                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2986                              <1> 	;;mov	ax, [ii] ; i-number
  2987                              <1> 	;call	iclose
  2988                              <1> 	;	; jsr r0,iclose / does nothing
  2989 00004790 31C0                <1>         xor     eax, eax
  2990 00004792 FEC0                <1> 	inc	al
  2991 00004794 66A3[FC6E0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2992 0000479A 66A3[FE6E0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2993                              <1> 	; 02/07/2015
  2994 000047A0 833D[156F0000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2995 000047A7 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2996                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2997 000047A9 8B15[F86A0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2998 000047AF 8915[156F0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2999                              <1> sysexec_18:
  3000                              <1> 	; 18/10/2015
  3001                              <1> 	; 05/08/2015
  3002                              <1> 	; 29/07/2015
  3003 000047B5 8B2D[386F0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  3004                              <1> 			    ; list pointers (argument count)
  3005 000047BB FA                  <1> 	cli
  3006 000047BC 8B25[946A0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3007                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3008                              <1> 			    ; for this process	 
  3009                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3010                              <1> 	;xor	eax, eax ; 0
  3011 000047C2 FEC8                <1> 	dec	al ; eax = 0
  3012 000047C4 66BA2300            <1> 	mov	dx, UDATA
  3013 000047C8 6652                <1> 	push	dx  ; user's stack segment
  3014 000047CA 55                  <1> 	push	ebp ; user's stack pointer
  3015                              <1> 		    ; (points to number of arguments)
  3016 000047CB FB                  <1> 	sti
  3017 000047CC 9C                  <1> 	pushfd	; EFLAGS
  3018                              <1> 		; Set IF for enabling interrupts in user mode	
  3019                              <1> 	;or	dword [esp], 200h 
  3020                              <1> 	;
  3021                              <1> 	;mov	bx, UCODE
  3022                              <1> 	;push	bx ; user's code segment
  3023 000047CD 6A1B                <1> 	push	UCODE
  3024                              <1> 	;push	0
  3025 000047CF 50                  <1> 	push	eax ; EIP (=0) - start address -	
  3026                              <1> 		; clr -(r5) / popped into ps when rti in 
  3027                              <1> 			  ; / sysrele is executed
  3028                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3029                              <1> 		                ; / in sysrele is executed
  3030                              <1> 		;mov r5,0f / load second copyz argument
  3031                              <1> 		;tst -(r5) / decrement r5
  3032 000047D0 8925[B06E0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3033                              <1> 	; 05/08/2015
  3034                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3035                              <1> 	; ('push dx' would cause to general protection fault, 
  3036                              <1> 	; after 'pop ds' etc.)
  3037                              <1> 	;
  3038                              <1> 	;; push dx ; ds (UDATA)
  3039                              <1> 	;; push dx ; es (UDATA)
  3040                              <1> 	;; push dx ; fs (UDATA)
  3041                              <1> 	;; push dx ; gs (UDATA)
  3042                              <1> 	;
  3043                              <1> 	; This is a trick to prevent general protection fault
  3044                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3045 000047D6 8EC2                <1> 	mov 	es, dx ; UDATA
  3046 000047D8 06                  <1> 	push 	es ; ds (UDATA)
  3047 000047D9 06                  <1> 	push 	es ; es (UDATA)
  3048 000047DA 06                  <1> 	push 	es ; fs (UDATA)
  3049 000047DB 06                  <1> 	push	es ; gs (UDATA)
  3050 000047DC 66BA1000            <1> 	mov	dx, KDATA
  3051 000047E0 8EC2                <1> 	mov	es, dx
  3052                              <1> 	;
  3053                              <1> 	;; pushad simulation
  3054 000047E2 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3055 000047E4 50                  <1> 	push	eax ; eax (0)
  3056 000047E5 50                  <1> 	push	eax ; ecx (0)
  3057 000047E6 50                  <1> 	push	eax ; edx (0)
  3058 000047E7 50                  <1> 	push	eax ; ebx (0)
  3059 000047E8 55                  <1> 	push	ebp ; esp before pushad
  3060 000047E9 50                  <1> 	push	eax ; ebp (0)
  3061 000047EA 50                  <1> 	push	eax ; esi (0)		
  3062 000047EB 50                  <1> 	push	eax ; edi (0)	
  3063                              <1> 	;
  3064 000047EC A3[B86E0000]        <1> 	mov	[u.r0], eax ; eax = 0
  3065 000047F1 8925[B46E0000]      <1> 	mov	[u.usp], esp
  3066                              <1> 		; mov r5,u.r0 /
  3067                              <1> 		; sub $16.,r5 / skip 8 words
  3068                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3069                              <1> 		;             / effectively zeroes all regs
  3070                              <1> 			    ; / when sysrele is executed
  3071                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3072                              <1> 		; clr u.break
  3073                              <1> 		; mov r5,sp / point sp to user's stack
  3074                              <1> 	;
  3075 000047F7 E9FAF2FFFF          <1> 	jmp	sysret0
  3076                              <1> 	;jmp	sysret
  3077                              <1> 		; br sysret3 / return to core image at $core
  3078                              <1> 
  3079                              <1> get_argp:
  3080                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3081                              <1> 	; 18/10/2015 (nbase, ncount)
  3082                              <1> 	; 21/07/2015
  3083                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3084                              <1> 	; Get (virtual) address of argument from user's core memory
  3085                              <1> 	;
  3086                              <1> 	; INPUT:
  3087                              <1> 	;	esi = virtual address of argument pointer
  3088                              <1> 	; OUTPUT:
  3089                              <1> 	;	eax = virtual address of argument
  3090                              <1> 	;
  3091                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3092                              <1> 	;
  3093 000047FC 833D[156F0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3094                              <1> 				    ; (the caller is kernel)
  3095                              <1> 	;jna	short get_argpk 
  3096                              <1> 	; 24/12/2021
  3097 00004803 7719                <1> 	ja	short get_argp5
  3098                              <1> get_argpk:
  3099                              <1> 	; Argument is in kernel's memory space
  3100 00004805 66C705[346F0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3100 0000480D 10                  <1>
  3101 0000480E 8935[306F0000]      <1> 	mov	[nbase], esi
  3102 00004814 8305[306F0000]04    <1> 	add	dword [nbase], 4
  3103 0000481B 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3104 0000481D C3                  <1> 	retn
  3105                              <1> get_argp5:
  3106 0000481E 89F3                <1>      	mov	ebx, esi
  3107 00004820 E87FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3108 00004825 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  3109 00004827 A3[306F0000]        <1> 	mov 	[nbase], eax ; physical address	
  3110 0000482C 66890D[346F0000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3111 00004833 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3112                              <1> 	;cmp	cx, ax ; 4
  3113 00004838 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3114 0000483A 734C                <1> 	jnb	short get_argp2
  3115 0000483C 89F3                <1> 	mov	ebx, esi
  3116 0000483E 01CB                <1> 	add	ebx, ecx
  3117 00004840 E85FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3118 00004845 7237                <1> 	jc	short get_argp_err
  3119                              <1> 	;push	esi
  3120 00004847 89C6                <1> 	mov	esi, eax
  3121 00004849 66870D[346F0000]    <1> 	xchg	cx, [ncount]
  3122 00004850 8735[306F0000]      <1> 	xchg	esi, [nbase]
  3123 00004856 B504                <1> 	mov	ch, 4
  3124 00004858 28CD                <1> 	sub	ch, cl
  3125                              <1> get_argp0:
  3126 0000485A AC                  <1> 	lodsb
  3127                              <1> 	;push	ax
  3128                              <1> 	; 24/12/2021
  3129 0000485B 50                  <1> 	push	eax
  3130 0000485C FEC9                <1> 	dec	cl
  3131 0000485E 75FA                <1>         jnz     short get_argp0
  3132 00004860 8B35[306F0000]      <1> 	mov	esi, [nbase]
  3133                              <1> 	; 21/07/2015
  3134 00004866 0FB6C5              <1> 	movzx	eax, ch
  3135 00004869 0105[306F0000]      <1> 	add	[nbase], eax
  3136 0000486F 662905[346F0000]    <1> 	sub	[ncount], ax
  3137                              <1> get_argp1:
  3138 00004876 AC                  <1> 	lodsb
  3139 00004877 FECD                <1> 	dec	ch
  3140 00004879 7423                <1>         jz      short get_argp3
  3141                              <1> 	;push	ax
  3142                              <1> 	; 24/12/2021
  3143 0000487B 50                  <1> 	push	eax
  3144 0000487C EBF8                <1> 	jmp     short get_argp1
  3145                              <1> 	; 24/12/2021
  3146                              <1> get_argp_err:
  3147 0000487E A3[0D6F0000]        <1> 	mov	[u.error], eax
  3148 00004883 E94CF2FFFF          <1> 	jmp	error
  3149                              <1> get_argp2:
  3150                              <1> 	; 21/07/2015
  3151                              <1> 	;mov	eax, 4
  3152 00004888 8B15[306F0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3153 0000488E 0105[306F0000]      <1> 	add	[nbase], eax
  3154 00004894 662905[346F0000]    <1> 	sub	[ncount], ax
  3155                              <1> 	;
  3156 0000489B 8B02                <1> 	mov	eax, [edx]
  3157 0000489D C3                  <1> 	retn
  3158                              <1> get_argp3:
  3159 0000489E B103                <1> 	mov	cl, 3
  3160                              <1> get_argp4:
  3161 000048A0 C1E008              <1> 	shl	eax, 8
  3162                              <1> 	;pop	dx
  3163                              <1> 	; 24/12/2021
  3164 000048A3 5A                  <1> 	pop	edx
  3165 000048A4 88D0                <1> 	mov 	al, dl
  3166 000048A6 E2F8                <1>         loop    get_argp4
  3167                              <1> 	;pop	esi
  3168 000048A8 C3                  <1> 	retn	
  3169                              <1> 
  3170                              <1> sysfstat:
  3171                              <1> 	; 03/02/2022
  3172                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3173                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3174                              <1> 	;
  3175                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3176                              <1> 	; on open files instead of files given by name. It puts the
  3177                              <1> 	; buffer address on the stack, gets the i-number and
  3178                              <1> 	; checks to see if the file is open for reading or writing.
  3179                              <1> 	; If the file is open for writing (i-number is negative)
  3180                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3181                              <1> 	; is made.	
  3182                              <1> 	;
  3183                              <1> 	; Calling sequence:
  3184                              <1> 	;	sysfstat; buf
  3185                              <1> 	; Arguments:
  3186                              <1> 	;	buf - buffer address
  3187                              <1> 	;
  3188                              <1> 	; Inputs: *u.r0 - file descriptor
  3189                              <1> 	; Outputs: buffer is loaded with file information
  3190                              <1> 	; ...............................................................
  3191                              <1> 	;				
  3192                              <1> 	; Retro UNIX 8086 v1 modification:
  3193                              <1> 	;       'sysfstat' system call has two arguments; so,
  3194                              <1> 	;	* 1st argument, file descriptor is in BX register
  3195                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3196                              <1> 
  3197                              <1> 	; / set status of open file
  3198                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3199 000048A9 51                  <1> 	push	ecx
  3200                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3201                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3202                              <1> 		; jsr r0,getf / get the files i-number
  3203                              <1> 	; BX = file descriptor (file number)
  3204 000048AA E8F2000000          <1> 	call	getf1
  3205                              <1> 	; 03/02/2022
  3206 000048AF 21C0                <1> 	and	eax, eax
  3207                              <1> 	;and	ax, ax ; i-number of the file
  3208                              <1> 		; tst	r1 / is it 0?
  3209                              <1> 	;jz	error
  3210                              <1> 		; beq error3 / yes, error
  3211 000048B1 750F                <1> 	jnz	short sysfstat1
  3212 000048B3 C705[0D6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3212 000048BB 0000                <1>
  3213 000048BD E912F2FFFF          <1> 	jmp	error
  3214                              <1> sysfstat1:
  3215 000048C2 80FC80              <1> 	cmp	ah, 80h
  3216 000048C5 7222                <1>         jb      short sysstat1
  3217                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3218 000048C7 66F7D8              <1> 	neg	ax
  3219                              <1> 		; neg r1 / make it positive, then branch
  3220 000048CA EB1D                <1> 	jmp	short sysstat1
  3221                              <1> 		; br 1f / to 1f
  3222                              <1> sysstat:
  3223                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3224                              <1> 	; 18/10/2015
  3225                              <1> 	; 07/10/2015
  3226                              <1> 	; 02/09/2015
  3227                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3228                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3229                              <1> 	;
  3230                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3231                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3232                              <1> 	; long and information about the file placed in it.	
  3233                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3234                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3235                              <1> 	; is then loaded and the results are given in the UNIX
  3236                              <1> 	; Programmers Manual sysstat (II).	
  3237                              <1> 	;
  3238                              <1> 	; Calling sequence:
  3239                              <1> 	;	sysstat; name; buf
  3240                              <1> 	; Arguments:
  3241                              <1> 	;	name - points to the name of the file
  3242                              <1> 	;	buf - address of a 34 bytes buffer
  3243                              <1> 	; Inputs: -
  3244                              <1> 	; Outputs: buffer is loaded with file information
  3245                              <1> 	; ...............................................................
  3246                              <1> 	;				
  3247                              <1> 	; Retro UNIX 8086 v1 modification: 
  3248                              <1> 	;       'sysstat' system call has two arguments; so,
  3249                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3250                              <1> 	;	to get sysstat system call arguments from the user;
  3251                              <1> 	;	* 1st argument, name is pointed to by BX register
  3252                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3253                              <1> 	;
  3254                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3255                              <1> 	;	      arguments which were in these registers;
  3256                              <1> 	;	      but, it returns by putting the 1st argument
  3257                              <1> 	;	      in 'u.namep' and the 2nd argument
  3258                              <1> 	;	      on top of stack. (1st argument is offset of the
  3259                              <1> 	;	      file/path name in the user's program segment.)		 	
  3260                              <1> 	
  3261                              <1> 	; / ; name of file; buffer - get files status
  3262                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3263 000048CC 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  3264 000048D2 51                  <1> 	push	ecx
  3265 000048D3 E8FA000000          <1> 	call	namei
  3266                              <1> 		; jsr r0,namei / get the i-number for the file
  3267                              <1> 	;jc	error
  3268                              <1> 		; br error3 / no such file, error
  3269 000048D8 730F                <1> 	jnc	short sysstat1
  3270                              <1> 	; pop 	ecx
  3271                              <1> sysstat_err0:
  3272                              <1> 	; 'file not found !' error
  3273 000048DA C705[0D6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3273 000048E2 0000                <1>
  3274 000048E4 E9EBF1FFFF          <1> 	jmp	error
  3275                              <1> 
  3276                              <1> ;statx: db 0
  3277                              <1> 
  3278                              <1> sysstat1: ; 1:
  3279 000048E9 E8A9080000          <1> 	call	iget
  3280                              <1> 		; jsr r0,iget / get the i-node into core
  3281                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3282                              <1> 	; 02/09/2015
  3283 000048EE 8F05[D86E0000]      <1> 	pop	dword [u.base]
  3284                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3285 000048F4 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3286 000048F9 730A                <1> 	jnc 	short sysstat2
  3287                              <1> sysstat_err1:
  3288 000048FB A3[0D6F0000]        <1> 	mov	dword [u.error], eax ; error code
  3289 00004900 E9CFF1FFFF          <1> 	jmp	error
  3290                              <1> sysstat2:
  3291 00004905 A0[9C6E0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3292 0000490A AA                  <1> 	stosb
  3293 0000490B FF05[D86E0000]      <1> 	inc 	dword [u.base]
  3294                              <1> 	;dec 	cx
  3295                              <1> 	; 24/12/2021
  3296 00004911 49                  <1> 	dec	ecx
  3297 00004912 7505                <1> 	jnz	short sysstat3
  3298 00004914 E835000000          <1> 	call	sysstat_gpa
  3299                              <1> 	;jc	short sysstat_err1
  3300                              <1> sysstat3:
  3301 00004919 A0[9D6E0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3302 0000491E AA                  <1> 	stosb
  3303                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3304 0000491F FF05[D86E0000]      <1> 	inc 	dword [u.base]
  3305                              <1> 	;;dec 	word [u.pcount]
  3306                              <1> 	;dec	cx
  3307 00004925 49                  <1> 	dec	ecx ; 24/12/2021
  3308 00004926 7505                <1> 	jnz	short sysstat4
  3309 00004928 E821000000          <1> 	call	sysstat_gpa
  3310                              <1> 	;jc	short sysstat_err1	
  3311                              <1> sysstat4:
  3312 0000492D BE[B86B0000]        <1> 	mov	esi, inode
  3313                              <1> 		; mov $inode,r2 / r2 points to i-node
  3314                              <1> sysstat5: ; 1:
  3315 00004932 A4                  <1> 	movsb
  3316                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3317 00004933 FF05[D86E0000]      <1> 	inc 	dword [u.base]
  3318                              <1> 	;;dec 	word [u.pcount]
  3319                              <1> 	;dec 	cx
  3320                              <1> 	; 24/12/2021
  3321 00004939 49                  <1> 	dec	ecx
  3322 0000493A 7505                <1> 	jnz	short sysstat6
  3323 0000493C E80D000000          <1> 	call	sysstat_gpa
  3324                              <1> 	;jc	short sysstat_err1
  3325                              <1> sysstat6:		
  3326 00004941 81FE[D86B0000]      <1> 	cmp	esi, inode + 32
  3327                              <1> 		; cmp r2,$inode+32 / done?
  3328 00004947 75E9                <1> 	jne	short sysstat5
  3329                              <1> 		; bne 1b / no, go back
  3330 00004949 E9A6F1FFFF          <1> 	jmp	sysret
  3331                              <1> 		; br sysret3 / return through sysret
  3332                              <1> 	;
  3333                              <1> sysstat_gpa: ; get physical address of file status buffer
  3334                              <1> 	; 02/09/2015
  3335 0000494E 8B1D[D86E0000]      <1> 	mov 	ebx, [u.base]
  3336                              <1> 	; 07/10/2015
  3337 00004954 E84BE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3338                              <1> 	;jc	short sysstat_gpa1
  3339 00004959 72A0                <1> 	jc	short sysstat_err1
  3340                              <1> 	; 18/10/2015
  3341 0000495B 89C7                <1> 	mov	edi, eax ; physical address
  3342                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3343                              <1> ;sysstat_gpa1:
  3344 0000495D C3                  <1> 	retn
  3345                              <1> 
  3346                              <1> fclose:
  3347                              <1> 	; 08/01/2022
  3348                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3349                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3350                              <1> 	;            (32 bit offset pointer modification)
  3351                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3352                              <1> 	;
  3353                              <1> 	; Given the file descriptor (index to the u.fp list)
  3354                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3355                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3356                              <1> 	; u.fp list is cleared. If all the processes that opened
  3357                              <1> 	; that file close it, then fsp etry is freed and the file
  3358                              <1> 	; is closed. If not a return is taken. 
  3359                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3360                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3361                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3362                              <1> 	; a check is made to see if the file is special.	
  3363                              <1> 	;
  3364                              <1> 	; INPUTS ->
  3365                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3366                              <1> 	;    u.fp - list of entries in the fsp table
  3367                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3368                              <1> 	; OUTPUTS ->
  3369                              <1> 	;    r1 - contains the same file descriptor
  3370                              <1> 	;    r2 - contains i-number
  3371                              <1> 	;
  3372                              <1> 	; ((AX = R1))
  3373                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3374                              <1> 	;
  3375                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3376                              <1> 	;              if i-number of the file is 0. (error)  	
  3377                              <1> 
  3378                              <1> 	;movzx	edx, ax ; **
  3379                              <1> 	; 24/12/2021
  3380                              <1> 	;movzx	edx, al
  3381 0000495E 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3382 00004960 50                  <1> 	push	eax ; ***
  3383                              <1> 	;push	ax ; ***
  3384                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3385                              <1> 			     ; / the index to u.fp list)
  3386 00004961 E839000000          <1> 	call	getf
  3387                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3388                              <1> 			    ; / cdev has device =, u.fofp 
  3389                              <1> 			    ; / points to 3rd word of fsp entry
  3390 00004966 6683F801            <1> 	cmp	ax, 1 ; r1
  3391                              <1> 		; tst r1 / is i-number 0?
  3392 0000496A 7231                <1> 	jb	short fclose_2
  3393                              <1> 		; beq 1f / yes, i-node not active so return
  3394                              <1> 		; tst (r0)+ / no, jump over error return
  3395 0000496C 89D3                <1> 	mov	ebx, edx ; **
  3396                              <1> 	; 24/12/2021
  3397 0000496E 89C2                <1> 	mov	edx, eax ; *
  3398                              <1> 	;mov 	dx, ax ; *
  3399                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3400                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3401                              <1> 			    ; / which is index to u.fp ; **
  3402 00004970 C683[BE6E0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3403                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3404 00004977 8B1D[C86E0000]      <1> 	mov	ebx, [u.fofp]
  3405                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3406                              <1> fclose_0:
  3407 0000497D FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3408                              <1> 		; decb 2(r1) / decrement the number of processes 
  3409                              <1> 			   ; / that have opened the file
  3410 00004980 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3411                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3412                              <1> 	;
  3413                              <1> 	; 24/12/2021
  3414 00004982 52                  <1> 	push	edx ; *
  3415                              <1> 	;push	dx ; *
  3416                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3417                              <1> 	;xor	ax, ax ; 0
  3418                              <1> 	; 24/12/2021
  3419 00004983 31C0                <1> 	xor	eax, eax
  3420 00004985 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3421                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3422 00004989 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3423                              <1> 		; tstb	3(r1) / has this file been deleted
  3424 0000498C 20C0                <1> 	and	al, al
  3425 0000498E 7407                <1> 	jz	short fclose_1
  3426                              <1> 		; beq 2f / no, branch
  3427                              <1> 	; 08/01/2022
  3428 00004990 89D0                <1> 	mov	eax, edx
  3429                              <1> 	;mov	ax, dx ; *
  3430                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3431                              <1> 	; AX = inode number
  3432 00004992 E857040000          <1> 	call	anyi
  3433                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3434                              <1> 			    ; / check if file appears in fsp again
  3435                              <1> fclose_1: ; 2:
  3436                              <1> 	; 24/12/2021
  3437 00004997 58                  <1> 	pop	eax ; * 
  3438                              <1> 	;pop	ax ; *
  3439                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3440 00004998 E8C1100000          <1> 	call	iclose ; close if it is special file 
  3441                              <1> 		; jsr r0,iclose / check to see if its a special file
  3442                              <1> fclose_2: ; 1:
  3443                              <1> 	; 24/12/2021
  3444 0000499D 58                  <1> 	pop	eax ; ***
  3445                              <1> 	;pop	ax ; ***
  3446                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3447 0000499E C3                  <1> 	retn
  3448                              <1> 		; rts r0
  3449                              <1> 
  3450                              <1> 	; 09/01/2022
  3451                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2)
  3452                              <1> getf:	; / get the device number and the i-number of an open file
  3453                              <1> 	; 13/05/2015
  3454                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3455                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3456                              <1> 	;
  3457 0000499F 89C3                <1> 	mov	ebx, eax
  3458                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3459                              <1> 	; 08/01/2022
  3460 000049A1 29C0                <1> 	sub	eax, eax
  3461                              <1> 	;
  3462 000049A3 83FB0A              <1> 	cmp	ebx, 10
  3463                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3464 000049A6 7329                <1>         jnb	short getf2 ; 13/05/2015
  3465                              <1> 	;jnb	error
  3466                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3467                              <1> 			    ; / index in fsp table
  3468                              <1> 	; 08/01/2022
  3469 000049A8 8A83[BE6E0000]      <1> 	mov	al, [ebx+u.fp]
  3470                              <1> 	;mov	bl, [ebx+u.fp]
  3471                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3472                              <1> 		                  ; / in fsp table
  3473                              <1> 	; 08/01/2022
  3474 000049AE 08C0                <1> 	or	al, al
  3475 000049B0 741F                <1> 	jz	short getf2	
  3476                              <1> 	;or	bl, bl
  3477                              <1> 	;jnz	short getf3
  3478                              <1> 	;;jz	short getf4
  3479                              <1> 		; beq 1f / if its zero return
  3480                              <1> ;getf2:
  3481                              <1> ;	; 08/01/2022
  3482                              <1> ;	; 'File not open !' error (ax=0)
  3483                              <1> ;	;sub	eax, eax
  3484                              <1> ;	retn
  3485                              <1> 
  3486                              <1> getf3:	
  3487                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3488                              <1> 	;
  3489                              <1> 	; 'fsp' table (10 bytes/entry)
  3490                              <1> 	; bit 15				   bit 0
  3491                              <1> 	; ---|-------------------------------------------
  3492                              <1> 	; r/w|		i-number of open file
  3493                              <1> 	; ---|-------------------------------------------
  3494                              <1> 	;		   device number
  3495                              <1> 	; -----------------------------------------------
  3496                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3497                              <1> 	; -----------------------------------------------
  3498                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3499                              <1> 	; ----------------------|------------------------
  3500                              <1> 	;  flag that says file 	| number of processes
  3501                              <1> 	;   has been deleted	| that have file open 
  3502                              <1> 	; ----------------------|------------------------
  3503                              <1> 	;
  3504                              <1> 	;mov	eax, 10
  3505                              <1> 	; 08/01/2022
  3506 000049B2 B30A                <1> 	mov	bl, 10
  3507 000049B4 F6E3                <1> 	mul	bl
  3508 000049B6 BB[826C0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3509 000049BB 01C3                <1> 	add	ebx, eax
  3510                              <1> 		; asl r1
  3511                              <1> 		; asl r1 / multiply by 8 to get index into 
  3512                              <1> 		       ; / fsp table entry
  3513                              <1> 		; asl r1
  3514                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3515                              <1> 			      ; / in the fsp entry
  3516 000049BD 891D[C86E0000]      <1> 	mov	[u.fofp], ebx
  3517                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3518                              <1> 			      ; / in fsp entry in u.fofp
  3519 000049C3 4B                  <1> 	dec	ebx
  3520 000049C4 4B                  <1> 	dec	ebx
  3521                              <1> 	;mov	ax, [ebx]
  3522                              <1> 	; 09/01/2022
  3523 000049C5 8A03                <1> 	mov	al, [ebx]
  3524 000049C7 A2[9F6E0000]        <1> 	mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3525                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3526                              <1> 			     ;;dev number is in 1 byte
  3527                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3528 000049CC 4B                  <1> 	dec	ebx
  3529 000049CD 4B                  <1> 	dec	ebx
  3530 000049CE 668B03              <1> 	mov	ax, [ebx]
  3531                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3532                              <1> getf2:	; 08/01/2022
  3533                              <1> getf4:	; 1:
  3534 000049D1 C3                  <1> 	retn
  3535                              <1> 		; rts r0
  3536                              <1> 
  3537                              <1> namei:
  3538                              <1> 	; 03/02/2022
  3539                              <1> 	; 09/01/2022
  3540                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3541                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3542                              <1> 	; 18/10/2015 (nbase, ncount)
  3543                              <1> 	; 12/10/2015
  3544                              <1> 	; 21/08/2015
  3545                              <1> 	; 18/07/2015
  3546                              <1> 	; 02/07/2015
  3547                              <1> 	; 17/06/2015
  3548                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3549                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3550                              <1> 	;
  3551                              <1> 	; 'namei' takes a file path name and returns i-number of
  3552                              <1> 	; the file in the current directory or the root directory
  3553                              <1> 	; (if the first character of the pathname is '/').	
  3554                              <1> 	;
  3555                              <1> 	; INPUTS ->
  3556                              <1> 	;    u.namep - points to a file path name
  3557                              <1> 	;    u.cdir - i-number of users directory
  3558                              <1> 	;    u.cdev - device number on which user directory resides	
  3559                              <1> 	; OUTPUTS ->
  3560                              <1> 	;    r1 - i-number of file
  3561                              <1> 	;    cdev
  3562                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3563                              <1> 	;               occurs in the search for file path name.
  3564                              <1> 	;	        If no match u.dirb points to the end of 
  3565                              <1> 	;               the directory and r1 = i-number of the current
  3566                              <1> 	;	        directory.	
  3567                              <1> 	; ((AX = R1))
  3568                              <1> 	;
  3569                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3570                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3571                              <1> 	;
  3572                              <1> 
  3573 000049D2 66A1[BC6E0000]      <1> 	mov	ax, [u.cdir]
  3574                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3575                              <1> 			      ; / in r1
  3576                              <1> 	; 09/01/2022
  3577 000049D8 8A15[026F0000]      <1> 	mov	dl, [u.cdrv]
  3578 000049DE 8815[9F6E0000]      <1> 	mov	[cdev], dl
  3579                              <1> 	;mov	dx, [u.cdrv]
  3580                              <1> 	;mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3581                              <1> 				    ; device/drive number is in 1 byte, 
  3582                              <1> 				    ; not in 1 word!
  3583                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3584                              <1> 				; / into cdev
  3585                              <1> 	; 12/10/2015
  3586                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3587                              <1>       	 ; convert virtual (pathname) addr to physical address
  3588 000049E4 E822010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3589                              <1> 		; esi = physical address of [u.namep]
  3590                              <1> 		; ecx = byte count in the page
  3591 000049E9 803E2F              <1> 	cmp	byte [esi], '/'
  3592                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3593 000049EC 751D                <1> 	jne	short namei_1
  3594                              <1> 		; bne 1f
  3595 000049EE FF05[D06E0000]      <1> 	inc	dword [u.namep]
  3596                              <1> 		; inc u.namep / go to next char
  3597                              <1> 	;dec	cx ; remain byte count in the page
  3598                              <1> 	; 24/12/2021
  3599 000049F4 49                  <1> 	dec	ecx
  3600 000049F5 7506                <1> 	jnz	short namei_0
  3601                              <1> 	; 12/10/2015
  3602 000049F7 E80F010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3603                              <1> 		; esi = physical address (page start + offset)
  3604                              <1> 		; ecx = byte count in the page
  3605 000049FC 4E                  <1> 	dec	esi
  3606                              <1> namei_0:
  3607 000049FD 46                  <1> 	inc 	esi  ; go to next char
  3608 000049FE 66A1[A86E0000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3609                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3610 00004A04 C605[9F6E0000]00    <1> 	mov	byte [cdev], 0
  3611                              <1> 		; clr cdev / clear device number
  3612                              <1> namei_1: ; 1:
  3613 00004A0B F606FF              <1> 	test	byte [esi], 0FFh
  3614                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3615 00004A0E 74C1                <1> 	jz	short getf4
  3616                              <1> 	;jz	nig
  3617                              <1> 		; tstb *u.namep / is the character in file name a nul
  3618                              <1> 		; beq nig / yes, end of file name reached; 
  3619                              <1> 			; / branch to "nig"
  3620                              <1> namei_2: ; 1:
  3621                              <1> 	; 18/10/2015
  3622 00004A10 8935[306F0000]      <1> 	mov 	[nbase], esi
  3623 00004A16 66890D[346F0000]    <1> 	mov 	[ncount], cx
  3624                              <1> 	;
  3625                              <1> 	;mov	dx, 2
  3626 00004A1D B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3627 00004A1F E847080000          <1> 	call	access
  3628                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3629                              <1> 	; 'access' will not return here if user has not "r" permission !
  3630                              <1> 	; 03/02/2022
  3631 00004A24 F605[B96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3632                              <1> 	;test 	word [i.flgs], 4000h
  3633                              <1> 		; bit $40000,i.flgs / directory i-node?
  3634 00004A2B 746A                <1>         jz      short namei_err
  3635                              <1> 		; beq error3 / no, got an error
  3636                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3637 00004A2D 31C0                <1> 	xor	eax, eax
  3638 00004A2F A3[D46E0000]        <1> 	mov	[u.off], eax ; 0
  3639 00004A34 66A1[BC6B0000]      <1> 	mov	ax, [i.size]
  3640 00004A3A A3[CC6E0000]        <1> 	mov	[u.dirp], eax
  3641                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3642                              <1> 		; clr u.off / u.off is file offset used by user
  3643 00004A3F C705[C86E0000]-     <1> 	mov	dword [u.fofp], u.off
  3643 00004A45 [D46E0000]          <1>
  3644                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3645                              <1> 				  ; / the offset portion of fsp entry
  3646                              <1> namei_3: ; 2:
  3647 00004A49 C705[D86E0000]-     <1> 	mov	dword [u.base], u.dirbuf
  3647 00004A4F [EA6E0000]          <1>
  3648                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3649                              <1> 				    ; / copied from a directory
  3650 00004A53 C705[DC6E0000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3650 00004A5B 0000                <1>
  3651                              <1>  		; mov $10.,u.count / u.count is byte count 
  3652                              <1> 				 ; / for reads and writes
  3653 00004A5D 66A1[9C6E0000]      <1> 	mov 	ax, [ii]
  3654                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3655 00004A63 FE05[1F6F0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3656 00004A69 E8FD080000          <1>     	call	readi
  3657                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3658                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3659 00004A6E 8B0D[E06E0000]      <1> 	mov 	ecx, [u.nread]
  3660 00004A74 09C9                <1> 	or 	ecx, ecx
  3661                              <1> 		; tst u.nread
  3662 00004A76 741B                <1> 	jz	short nib
  3663                              <1> 		; ble nib / gives error return
  3664                              <1> 	;
  3665 00004A78 668B1D[EA6E0000]    <1> 	mov 	bx, [u.dirbuf]
  3666 00004A7F 6621DB              <1> 	and 	bx, bx       
  3667                              <1> 		; tst u.dirbuf /
  3668 00004A82 7522                <1> 	jnz	short namei_4
  3669                              <1> 		; bne 3f / branch when active directory entry 
  3670                              <1> 		       ; / (i-node word in entry non zero)
  3671 00004A84 A1[D46E0000]        <1> 	mov	eax, [u.off]
  3672 00004A89 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3673 00004A8C A3[CC6E0000]        <1> 	mov	[u.dirp], eax
  3674                              <1> 		; mov u.off,u.dirp
  3675                              <1> 		; sub $10.,u.dirp
  3676 00004A91 EBB6                <1> 	jmp	short namei_3
  3677                              <1> 		; br 2b
  3678                              <1> 
  3679                              <1> 	; 18/07/2013
  3680                              <1> nib: 
  3681 00004A93 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3682 00004A95 F9                  <1> 	stc
  3683                              <1> nig:
  3684 00004A96 C3                  <1> 	retn
  3685                              <1> 
  3686                              <1> namei_err:
  3687                              <1> 	; 16/06/2015
  3688 00004A97 C705[0D6F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3688 00004A9F 0000                <1>
  3689 00004AA1 E92EF0FFFF          <1> 	jmp	error
  3690                              <1> 
  3691                              <1> namei_4: ; 3:
  3692                              <1> 	; 18/10/2015
  3693                              <1> 	; 12/10/2015
  3694                              <1> 	; 21/08/2015
  3695                              <1> 	; 18/07/2015
  3696 00004AA6 8B2D[D06E0000]      <1> 	mov	ebp, [u.namep]
  3697                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3698 00004AAC BF[EC6E0000]        <1> 	mov 	edi, u.dirbuf + 2
  3699                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3700                              <1> 	; 18/10/2015
  3701 00004AB1 8B35[306F0000]      <1> 	mov	esi, [nbase]	
  3702 00004AB7 668B0D[346F0000]    <1> 	mov	cx, [ncount]
  3703                              <1> 	;
  3704 00004ABE 6621C9              <1> 	and	cx, cx
  3705 00004AC1 7505                <1> 	jnz	short namei_5	
  3706                              <1> 	;
  3707 00004AC3 E849000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3708                              <1> 		; esi = physical address (page start + offset)
  3709                              <1> 		; ecx = byte count in the page
  3710                              <1> namei_5: ; 3:
  3711 00004AC8 45                  <1> 	inc	ebp ; 18/07/2015
  3712 00004AC9 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3713                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3714 00004ACA 08C0                <1> 	or 	al, al
  3715 00004ACC 741C                <1> 	jz 	short namei_7
  3716                              <1> 		; beq 3f / if char is nul, then the last char in string
  3717                              <1> 			; / has been moved
  3718 00004ACE 3C2F                <1> 	cmp	al, '/'
  3719                              <1> 		; cmp r4,$'/ / is char a </>
  3720 00004AD0 7418                <1> 	je 	short namei_7
  3721                              <1> 		; beq 3f	
  3722                              <1> 	; 24/12/2021
  3723 00004AD2 49                  <1> 	dec	ecx
  3724                              <1> 	; 12/10/2015
  3725                              <1> 	;dec	cx ; remain byte count in the page
  3726 00004AD3 7505                <1> 	jnz	short namei_6
  3727 00004AD5 E837000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3728                              <1> 		; esi = physical address (page start + offset)
  3729                              <1> 		; ecx = byte count in the page
  3730                              <1> namei_6:
  3731 00004ADA 81FF[FA6E0000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3732                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3733                              <1> 				     ; / all 8 bytes of file name
  3734 00004AE0 74E6                <1> 	je	short namei_5
  3735                              <1> 		; beq 3b
  3736 00004AE2 AE                  <1> 	scasb	
  3737                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3738                              <1> 			      ; / char read from directory
  3739 00004AE3 74E3                <1> 	je 	short namei_5
  3740                              <1> 		; beq 3b / branch if chars match
  3741                              <1> namei_9:
  3742 00004AE5 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3743                              <1> 		; br 2b / file names do not match go to next directory entry
  3744                              <1> namei_7: ; 3:
  3745 00004AEA 81FF[FA6E0000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3746                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3747 00004AF0 7406                <1> 	je	short namei_8
  3748                              <1> 		; beq 3f
  3749 00004AF2 8A27                <1> 	mov 	ah, [edi]
  3750                              <1> 	;inc 	edi 
  3751 00004AF4 20E4                <1> 	and 	ah, ah
  3752                              <1> 		; tstb (r3)+ /
  3753                              <1>         ;jnz	namei_3
  3754                              <1> 		; bne 2b
  3755                              <1> 	; 24/12/2021
  3756 00004AF6 75ED                <1> 	jnz	short namei_9	
  3757                              <1> namei_8: ; 3
  3758 00004AF8 892D[D06E0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3759                              <1> 		; mov r2,u.namep / u.namep points to char 
  3760                              <1> 			       ; / following a / or nul
  3761                              <1> 	;mov	bx, [u.dirbuf]
  3762                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3763                              <1> 				; / entry to r1
  3764 00004AFE 20C0                <1> 	and 	al, al
  3765                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3766                              <1> 		      ;  / if r4 = </> then go to next directory
  3767                              <1> 	;mov	ax, bx
  3768 00004B00 66A1[EA6E0000]      <1> 	mov 	ax, [u.dirbuf] ; 17/06/2015
  3769                              <1>   	; 24/12/2021
  3770 00004B06 E903FFFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3771                              <1> 	;jnz	namei_2 
  3772                              <1> 		; bne 1b
  3773                              <1> 	; AX = i-number of the file
  3774                              <1> ;;nig:
  3775                              <1> 	;retn	; 24/12/2021
  3776                              <1> 		; tst (r0)+ / gives non-error return
  3777                              <1> ;;nib:
  3778                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3779                              <1> 		       ; ax = 0 -> file not found 
  3780                              <1> ;;	stc	; 27/05/2013
  3781                              <1> ;;	retn
  3782                              <1> 		; rts r0
  3783                              <1> 
  3784                              <1> trans_addr_nmbp:
  3785                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3786                              <1> 	; 18/10/2015
  3787                              <1> 	; 12/10/2015
  3788 00004B0B 8B2D[D06E0000]      <1> 	mov 	ebp, [u.namep]
  3789                              <1> trans_addr_nm:
  3790                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 
  3791                              <1> 	; Convert virtual (pathname) address to physical address
  3792                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3793                              <1> 	; 18/10/2015
  3794                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3795                              <1> 	; 02/07/2015
  3796                              <1> 	; 17/06/2015
  3797                              <1> 	; 16/06/2015
  3798                              <1> 	;
  3799                              <1> 	; INPUTS: 
  3800                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3801                              <1> 	;	[u.pgdir] = user's page directory
  3802                              <1> 	; OUTPUT:
  3803                              <1> 	;       esi = physical address of the pathname
  3804                              <1> 	;	ecx = remain byte count in the page
  3805                              <1> 	;
  3806                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3807                              <1> 	;
  3808                              <1> 
  3809                              <1> 	; 08/01/2022
  3810 00004B11 29C9                <1> 	sub	ecx, ecx
  3811                              <1> 	;
  3812 00004B13 833D[156F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3813 00004B1A 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3814                              <1> 				     ; it is already physical address
  3815 00004B1C 50                  <1>    	push	eax	
  3816 00004B1D 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3817 00004B1F E880E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3818 00004B24 7204                <1> 	jc	short tr_addr_nm_err
  3819                              <1> 	; 18/10/2015
  3820                              <1> 	; eax = physical address 
  3821                              <1> 	; cx = remain byte count in page (1-4096) 
  3822                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3823 00004B26 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3824 00004B28 58                  <1> 	pop	eax 
  3825 00004B29 C3                  <1> 	retn
  3826                              <1> 
  3827                              <1> tr_addr_nm_err:
  3828 00004B2A A3[0D6F0000]        <1> 	mov	[u.error], eax
  3829                              <1> 	;pop 	eax
  3830 00004B2F E9A0EFFFFF          <1> 	jmp	error
  3831                              <1> 
  3832                              <1> trans_addr_nmk:
  3833                              <1> 	; 12/10/2015
  3834                              <1> 	; 02/07/2015
  3835 00004B34 8B35[D06E0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3836                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3837                              <1> 	; 08/01/2022
  3838 00004B3A B510                <1> 	mov	ch, PAGE_SIZE/256
  3839 00004B3C C3                  <1> 	retn
  3840                              <1> 
  3841                              <1> syschdir:
  3842                              <1> 	; / makes the directory specified in the argument
  3843                              <1> 	; / the current directory
  3844                              <1> 	;
  3845                              <1> 	; 09/01/2022
  3846                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3847                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3848                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3849                              <1> 	;
  3850                              <1> 	; 'syschdir' makes the directory specified in its argument
  3851                              <1> 	; the current working directory.
  3852                              <1> 	;
  3853                              <1> 	; Calling sequence:
  3854                              <1> 	;	syschdir; name
  3855                              <1> 	; Arguments:
  3856                              <1> 	;	name - address of the path name of a directory
  3857                              <1> 	;	       terminated by nul byte.	
  3858                              <1> 	; Inputs: -
  3859                              <1> 	; Outputs: -
  3860                              <1> 	; ...............................................................
  3861                              <1> 	;				
  3862                              <1> 	; Retro UNIX 8086 v1 modification:
  3863                              <1> 	;	 The user/application program puts address of 
  3864                              <1> 	;	 the path name in BX register as 'syschdir' 
  3865                              <1> 	; 	 system call argument.
  3866                              <1> 
  3867 00004B3D 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  3868                              <1> 		; jsr r0,arg; u.namep / u.namep points to path name
  3869 00004B43 E88AFEFFFF          <1> 	call	namei
  3870                              <1> 		; jsr r0,namei / find its i-number
  3871                              <1> 	;jc	error
  3872                              <1> 		; br error3
  3873 00004B48 730F                <1> 	jnc	short syschdir0
  3874                              <1> 	; 'directory not found !' error
  3875 00004B4A C705[0D6F0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3875 00004B52 0000                <1>
  3876 00004B54 E97BEFFFFF          <1> 	jmp	error
  3877                              <1> syschdir0:
  3878                              <1> 	; 08/01/2022
  3879 00004B59 B202                <1> 	mov	dl, 2  ; read access ; 08/01/2022 (BugFix)
  3880 00004B5B E80B070000          <1> 	call	access
  3881                              <1> 		; jsr r0,access; 2 / get i-node into core
  3882                              <1> 	; 08/01/2022
  3883 00004B60 F605[B96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3884                              <1> 	;test	word [i.flgs], 4000h
  3885                              <1> 		; bit $40000,i.flgs / is it a directory?
  3886                              <1> 	;jz	error 
  3887                              <1> 		; beq error3 / no error
  3888 00004B67 750F                <1> 	jnz	short syschdir1
  3889 00004B69 C705[0D6F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3889 00004B71 0000                <1>
  3890 00004B73 E95CEFFFFF          <1> 	jmp	error
  3891                              <1> syschdir1:
  3892 00004B78 66A3[BC6E0000]      <1> 	mov	[u.cdir], ax
  3893                              <1> 		; mov r1,u.cdir / move i-number to users 
  3894                              <1> 			      ; / current directory
  3895                              <1> 	; 09/01/2022
  3896 00004B7E A0[9F6E0000]        <1> 	mov	al, [cdev]
  3897 00004B83 A2[026F0000]        <1> 	mov	[u.cdrv], al
  3898                              <1> 	;mov	ax, [cdev]
  3899                              <1> 	;mov	[u.cdrv], ax
  3900                              <1> 		; mov cdev,u.cdev / move its device to users 
  3901                              <1> 			        ; / current device
  3902 00004B88 E967EFFFFF          <1> 	jmp	sysret
  3903                              <1> 		; br sysret3
  3904                              <1> 
  3905                              <1> syschmod: ; < change mode of file >
  3906                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3907                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3908                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3909                              <1> 	;
  3910                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3911                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3912                              <1> 	; changed to 'mode'.
  3913                              <1> 	;
  3914                              <1> 	; Calling sequence:
  3915                              <1> 	;	syschmod; name; mode
  3916                              <1> 	; Arguments:
  3917                              <1> 	;	name - address of the file name
  3918                              <1> 	;	       terminated by null byte.
  3919                              <1> 	;	mode - (new) mode/flags < attributes >
  3920                              <1> 	;	
  3921                              <1> 	; Inputs: -
  3922                              <1> 	; Outputs: -
  3923                              <1> 	; ...............................................................
  3924                              <1> 	;				
  3925                              <1> 	; Retro UNIX 8086 v1 modification: 
  3926                              <1> 	;       'syschmod' system call has two arguments; so,
  3927                              <1> 	;	* 1st argument, name is pointed to by BX register
  3928                              <1> 	;	* 2nd argument, mode is in CX register
  3929                              <1> 	;
  3930                              <1> 	; Mode bits (Flags):
  3931                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  3932                              <1> 	;	bit 14 - directory flag (4000h)
  3933                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  3934                              <1> 	;	bit 12 - large file flag (1000h)
  3935                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3936                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  3937                              <1> 	;	bit 4 - executable flag (10h)
  3938                              <1> 	;	bit 3 - read permission for owner (08h)
  3939                              <1> 	;	bit 2 - write permission for owner (04h)
  3940                              <1> 	;	bit 1 - read permission for non-owner (02h)
  3941                              <1> 	;	bit 0 - write permission for non-owner (01h)
  3942                              <1> 
  3943                              <1> 	; / name; mode
  3944 00004B8D E812000000          <1> 	call	isown
  3945                              <1> 		;jsr r0,isown / get the i-node and check user status
  3946                              <1> 	; 09/01/2022
  3947 00004B92 F605[B96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3948                              <1> 	;test	word [i.flgs], 4000h
  3949                              <1> 		; bit $40000,i.flgs / directory?
  3950 00004B99 7402                <1> 	jz	short syschmod1
  3951                              <1> 		; beq 2f / no
  3952                              <1> 	; AL = (new) mode
  3953 00004B9B 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3954                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3955                              <1> 			   ; / executable modes
  3956                              <1> syschmod1: ; 2:
  3957 00004B9D A2[B86B0000]        <1> 	mov	[i.flgs], al	
  3958                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3959 00004BA2 EB42                <1> 	jmp	short isown1
  3960                              <1> 		; br 1f
  3961                              <1> 
  3962                              <1> isown:
  3963                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3964                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3965                              <1> 	;
  3966                              <1> 	; 'isown' is given a file name (the 1st argument).
  3967                              <1> 	;  It find the i-number of that file via 'namei' 
  3968                              <1> 	;  then gets the i-node into core via 'iget'.
  3969                              <1> 	;  It then tests to see if the user is super user. 
  3970                              <1> 	;  If not, it cheks to see if the user is owner of 
  3971                              <1> 	;  the file. If he is not an error occurs.
  3972                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3973                              <1> 	;  the inode has been modified and the 2nd argument of
  3974                              <1> 	;  the call is put in r2.
  3975                              <1> 	;
  3976                              <1> 	; INPUTS ->
  3977                              <1> 	;    arguments of syschmod and syschown calls
  3978                              <1> 	; OUTPUTS ->
  3979                              <1> 	;    u.uid - id of user
  3980                              <1> 	;    imod - set to a 1
  3981                              <1> 	;    r2 - contains second argument of the system call				 	
  3982                              <1> 	;
  3983                              <1> 	;   ((AX=R2) output as 2nd argument)
  3984                              <1> 	;
  3985                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  3986                              <1> 	;
  3987                              <1> 		; jsr r0,arg2 / u.namep points to file name
  3988                              <1> 	;; ! 2nd argument on top of stack !
  3989                              <1> 	;; 22/06/2015 - 32 bit modifications
  3990                              <1> 	;; 07/07/2013
  3991 00004BA4 891D[D06E0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  3992 00004BAA 51                  <1> 	push 	ecx ;; 2nd argument
  3993                              <1> 	;;
  3994 00004BAB E822FEFFFF          <1> 	call	namei
  3995                              <1> 		; jsr r0,namei / get its i-number
  3996                              <1>        ; Retro UNIX 8086 v1 modification !
  3997                              <1>        ; ax = 0 -> file not found 
  3998                              <1> 	;and	ax, ax
  3999                              <1> 	;jz	error
  4000                              <1> 	;jc	error ; 27/05/2013
  4001                              <1> 		; br error3
  4002 00004BB0 730F                <1> 	jnc	short isown0
  4003                              <1> 	; 'file not found !' error
  4004 00004BB2 C705[0D6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4004 00004BBA 0000                <1>
  4005 00004BBC E913EFFFFF          <1> 	jmp	error
  4006                              <1> isown0:
  4007 00004BC1 E8D1050000          <1> 	call	iget
  4008                              <1> 		; jsr r0,iget / get i-node into core
  4009 00004BC6 A0[046F0000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4010 00004BCB 08C0                <1> 	or	al, al
  4011                              <1> 		; tstb u.uid / super user?
  4012 00004BCD 7417                <1> 	jz	short isown1
  4013                              <1> 		; beq 1f / yes, branch
  4014 00004BCF 3A05[BB6B0000]      <1> 	cmp	al, [i.uid]
  4015                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4016                              <1> 				 ; / the file
  4017                              <1> 	;jne	error
  4018                              <1> 		; beq 1f / yes
  4019                              <1> 		; jmp error3 / no, error
  4020 00004BD5 740F                <1> 	je	short isown1
  4021                              <1> 
  4022 00004BD7 C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4022 00004BDF 0000                <1>
  4023                              <1> 			;  'permission denied !' error
  4024 00004BE1 E9EEEEFFFF          <1> 	jmp	error
  4025                              <1> isown1: ; 1:
  4026 00004BE6 E8B6060000          <1> 	call	setimod
  4027                              <1> 		; jsr r0,setimod / indicates 
  4028                              <1> 		;	       ; / i-node has been modified
  4029 00004BEB 58                  <1> 	pop	eax ; 2nd argument
  4030                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4031                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4032 00004BEC C3                  <1> 	retn
  4033                              <1> 		; rts r0
  4034                              <1> 
  4035                              <1> ;;arg:  ; < get system call arguments >
  4036                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4037                              <1> 	; of form:
  4038                              <1> 	;	sys 'routine' ; arg1
  4039                              <1> 	;		or
  4040                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4041                              <1> 	;		or
  4042                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4043                              <1> 	;	
  4044                              <1> 	; INPUTS ->
  4045                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4046                              <1> 	;	This pointers's value is actually the value of
  4047                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4048                              <1> 	;	made to process the sys instruction
  4049                              <1> 	;    r0 - contains the return address for the routine
  4050                              <1> 	;	that called arg. The data in the word pointer 
  4051                              <1> 	;	to by the return address is used as address
  4052                              <1> 	;	in which the extracted argument is stored   		
  4053                              <1> 	;    	
  4054                              <1> 	; OUTPUTS ->
  4055                              <1> 	;    'address' - contains the extracted argument 
  4056                              <1> 	;    u.sp+18 - is incremented by 2 
  4057                              <1> 	;    r1 - contains the extracted argument
  4058                              <1> 	;    r0 - points to the next instruction to be
  4059                              <1> 	;	 executed in the calling routine.
  4060                              <1> 	;
  4061                              <1>   
  4062                              <1> 	; mov u.sp,r1
  4063                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4064                              <1> 			; / into argument of arg2
  4065                              <1> 	; add $2,18.(r1) / point pc on stack 
  4066                              <1> 			      ; / to next system argument
  4067                              <1> 	; rts r0
  4068                              <1> 
  4069                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4070                              <1> 	; 'arg2' takes first argument in system call
  4071                              <1> 	;  (pointer to name of the file) and puts it in location
  4072                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4073                              <1> 	;  and on top of the stack
  4074                              <1> 	;	
  4075                              <1> 	; INPUTS ->
  4076                              <1> 	;    u.sp, r0
  4077                              <1> 	;    	
  4078                              <1> 	; OUTPUTS ->
  4079                              <1> 	;    u.namep
  4080                              <1> 	;    u.off 
  4081                              <1> 	;    u.off pushed on stack
  4082                              <1> 	;    r1
  4083                              <1> 	;
  4084                              <1> 
  4085                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4086                              <1> 				; / first arg in sys call
  4087                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4088                              <1> 				; / second arg in sys call
  4089                              <1> 	; mov r0,r1 / r0 points to calling routine
  4090                              <1> 	; mov (sp),r0 / put operation code back in r0
  4091                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4092                              <1> 			; / on stack
  4093                              <1> 	; jmp (r1) / return to calling routine
  4094                              <1> 
  4095                              <1> syschown: ; < change owner of file >
  4096                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4097                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4098                              <1> 	;
  4099                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4100                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4101                              <1> 	; changed to 'owner'
  4102                              <1> 	;
  4103                              <1> 	; Calling sequence:
  4104                              <1> 	;	syschown; name; owner
  4105                              <1> 	; Arguments:
  4106                              <1> 	;	name - address of the file name
  4107                              <1> 	;	       terminated by null byte.
  4108                              <1> 	;	owner - (new) owner (number/ID)
  4109                              <1> 	;	
  4110                              <1> 	; Inputs: -
  4111                              <1> 	; Outputs: -
  4112                              <1> 	; ...............................................................
  4113                              <1> 	;				
  4114                              <1> 	; Retro UNIX 8086 v1 modification: 
  4115                              <1> 	;       'syschown' system call has two arguments; so,
  4116                              <1> 	;	* 1st argument, name is pointed to by BX register
  4117                              <1> 	;	* 2nd argument, owner number is in CX register
  4118                              <1> 	;
  4119                              <1> 	; / name; owner
  4120 00004BED E8B2FFFFFF          <1> 	call	isown
  4121                              <1> 		; jsr r0,isown / get the i-node and check user status
  4122 00004BF2 803D[046F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4123                              <1> 		; tstb u.uid / super user
  4124 00004BF9 7418                <1> 	jz	short syschown1
  4125                              <1> 		; beq 2f / yes, 2f
  4126 00004BFB F605[B86B0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4127                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4128                              <1> 	;jnz	error
  4129                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4130 00004C02 740F                <1> 	jz	short syschown1
  4131                              <1> 	; 'permission denied !'
  4132 00004C04 C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4132 00004C0C 0000                <1>
  4133 00004C0E E9C1EEFFFF          <1> 	jmp	error
  4134                              <1> syschown1: ; 2:
  4135                              <1> 	; AL = owner (number/ID)
  4136 00004C13 A2[BB6B0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4137                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4138                              <1> 			       ; / in the i-node
  4139 00004C18 E9D7EEFFFF          <1> 	jmp	sysret
  4140                              <1> 	; 1: 
  4141                              <1> 		; jmp sysret4
  4142                              <1> 	; 3:
  4143                              <1> 		; jmp	error
  4144                              <1> 
  4145                              <1> systime: ; / get time of year
  4146                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4147                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4148                              <1> 	;
  4149                              <1> 	; 20/06/2013
  4150                              <1> 	; 'systime' gets the time of the year.
  4151                              <1> 	; The present time is put on the stack.
  4152                              <1> 	;
  4153                              <1> 	; Calling sequence:
  4154                              <1> 	;	systime
  4155                              <1> 	; Arguments: -
  4156                              <1> 	;	
  4157                              <1> 	; Inputs: -
  4158                              <1> 	; Outputs: sp+2, sp+4 - present time
  4159                              <1> 	; ...............................................................
  4160                              <1> 	;	
  4161                              <1> 	; Retro UNIX 8086 v1 modification: 
  4162                              <1> 	;       'systime' system call will return to the user
  4163                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4164                              <1> 	;
  4165                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4166                              <1> 	;	system call for PC compatibility !!		 	
  4167                              <1> 
  4168 00004C1D E8F5E9FFFF          <1> 	call 	epoch
  4169 00004C22 A3[B86E0000]        <1> 	mov 	[u.r0], eax
  4170                              <1> 		; mov s.time,4(sp)
  4171                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4172                              <1> 				   ; / on the stack
  4173                              <1> 		; br sysret4
  4174 00004C27 E9C8EEFFFF          <1> 	jmp	sysret 
  4175                              <1> 
  4176                              <1> sysstime: ; / set time
  4177                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4178                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4179                              <1> 	;
  4180                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4181                              <1> 	;
  4182                              <1> 	; Calling sequence:
  4183                              <1> 	;	sysstime
  4184                              <1> 	; Arguments: -
  4185                              <1> 	;	
  4186                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4187                              <1> 	; Outputs: -
  4188                              <1> 	; ...............................................................
  4189                              <1> 	;	
  4190                              <1> 	; Retro UNIX 8086 v1 modification: 
  4191                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4192                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4193                              <1> 	; 
  4194                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4195                              <1> 	;	to get sysstime system call arguments from the user;
  4196                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4197                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4198                              <1> 	;
  4199                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4200                              <1> 	;	system call for PC compatibility !!	
  4201                              <1> 
  4202 00004C2C 803D[046F0000]00    <1> 	cmp	byte [u.uid], 0
  4203                              <1> 		; tstb u.uid / is user the super user
  4204                              <1> 	;ja	error
  4205                              <1> 		; bne error4 / no, error
  4206 00004C33 760F                <1> 	jna	short systime1
  4207                              <1> 	; 'permission denied !'
  4208 00004C35 C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4208 00004C3D 0000                <1>
  4209 00004C3F E990EEFFFF          <1> 	jmp	error
  4210                              <1> systime1:
  4211                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4212                              <1> 	; EBX = unix (epoch) time (from user)
  4213 00004C44 89D8                <1> 	mov	eax, ebx
  4214 00004C46 E84CEBFFFF          <1> 	call 	set_date_time
  4215                              <1> 		; mov 4(sp),s.time
  4216                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4217 00004C4B E9A4EEFFFF          <1> 	jmp	sysret
  4218                              <1> 		; br sysret4
  4219                              <1> 
  4220                              <1> sysbreak:
  4221                              <1> 	; 18/10/2015
  4222                              <1> 	; 07/10/2015
  4223                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4224                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4225                              <1> 	;
  4226                              <1> 	; 'sysbreak' sets the programs break points. 
  4227                              <1> 	; It checks the current break point (u.break) to see if it is
  4228                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4229                              <1> 	; even address (if it was odd) and the area between u.break
  4230                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4231                              <1> 	; in u.break and control is passed to 'sysret'.
  4232                              <1> 	;
  4233                              <1> 	; Calling sequence:
  4234                              <1> 	;	sysbreak; addr
  4235                              <1> 	; Arguments: -
  4236                              <1> 	;	
  4237                              <1> 	; Inputs: u.break - current breakpoint
  4238                              <1> 	; Outputs: u.break - new breakpoint 
  4239                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4240                              <1> 	; ...............................................................
  4241                              <1> 	;	
  4242                              <1> 	; Retro UNIX 8086 v1 modification:
  4243                              <1> 	;	The user/application program puts breakpoint address
  4244                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4245                              <1> 	; 	(argument transfer method 1)
  4246                              <1> 	;
  4247                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4248                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4249                              <1> 	;  NOTE:
  4250                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4251                              <1> 	;	'u.break' address) of user's memory for original unix's
  4252                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4253                              <1> 
  4254                              <1> 		; mov u.break,r1 / move users break point to r1
  4255                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4256                              <1> 		; blos 1f / yes, 1f
  4257                              <1> 	; 23/06/2015
  4258 00004C50 8B2D[E46E0000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4259                              <1> 	;and	ebp, ebp
  4260                              <1> 	;jz	short sysbreak_3 
  4261                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4262                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4263 00004C56 8B15[B06E0000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4264 00004C5C 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4265                              <1> 	; 07/10/2015
  4266 00004C5F 891D[E46E0000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4267                              <1> 	;
  4268 00004C65 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4269                              <1> 			   ; with top of user's stack (virtual!)
  4270 00004C67 7327                <1> 	jnb	short sysbreak_3
  4271                              <1> 		; cmp r1,sp / is it the same or higher 
  4272                              <1> 			  ; / than the stack?
  4273                              <1> 		; bhis 1f / yes, 1f
  4274 00004C69 89DE                <1> 	mov	esi, ebx
  4275 00004C6B 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4276 00004C6D 7621                <1> 	jna	short sysbreak_3 
  4277                              <1> 	;push	ebx
  4278                              <1> sysbreak_1:
  4279 00004C6F 89EB                <1> 	mov	ebx, ebp  
  4280 00004C71 E82EE5FFFF          <1> 	call	get_physical_addr ; get physical address
  4281 00004C76 0F82AEFEFFFF        <1> 	jc	tr_addr_nm_err
  4282                              <1> 	; 18/10/2015
  4283 00004C7C 89C7                <1> 	mov	edi, eax 
  4284 00004C7E 29C0                <1> 	sub	eax, eax ; 0
  4285                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4286 00004C80 39CE                <1> 	cmp	esi, ecx
  4287 00004C82 7302                <1> 	jnb	short sysbreak_2
  4288 00004C84 89F1                <1> 	mov	ecx, esi
  4289                              <1> sysbreak_2:
  4290 00004C86 29CE                <1> 	sub	esi, ecx
  4291 00004C88 01CD                <1> 	add	ebp, ecx
  4292 00004C8A F3AA                <1> 	rep 	stosb
  4293 00004C8C 09F6                <1> 	or	esi, esi
  4294 00004C8E 75DF                <1> 	jnz	short sysbreak_1
  4295                              <1> 	;
  4296                              <1> 		; bit $1,r1 / is it an odd address
  4297                              <1> 		; beq 2f / no, its even
  4298                              <1> 		; clrb (r1)+ / yes, make it even
  4299                              <1> 	; 2: / clear area between the break point and the stack
  4300                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4301                              <1> 		; bhis 1f / yes, quit
  4302                              <1> 		; clr (r1)+ / clear word
  4303                              <1> 		; br 2b / go back
  4304                              <1> 	;pop	ebx
  4305                              <1> sysbreak_3: ; 1:
  4306                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4307                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4308                              <1> 			; / in u.break (set new break point)
  4309                              <1> 		; br sysret4 / br sysret
  4310 00004C90 E95FEEFFFF          <1> 	jmp	sysret
  4311                              <1> 
  4312                              <1> maknod: 
  4313                              <1> 	; 11/02/2022
  4314                              <1> 	; 09/01/2022
  4315                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4316                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4317                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4318                              <1> 	;
  4319                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4320                              <1> 	; for this i-node in the current directory.
  4321                              <1> 	;
  4322                              <1> 	; INPUTS ->
  4323                              <1> 	;    r1 - contains mode
  4324                              <1> 	;    ii - current directory's i-number	
  4325                              <1> 	;    	
  4326                              <1> 	; OUTPUTS ->
  4327                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4328                              <1> 	;    i.flgs - flags in new i-node 
  4329                              <1> 	;    i.uid - filled with u.uid
  4330                              <1> 	;    i.nlks - 1 is put in the number of links
  4331                              <1> 	;    i.ctim - creation time				
  4332                              <1> 	;    i.ctim+2 - modification time
  4333                              <1> 	;    imod - set via call to setimod
  4334                              <1> 	;	
  4335                              <1> 	; ((AX = R1)) input
  4336                              <1> 	;
  4337                              <1> 	; (Retro UNIX Prototype : 
  4338                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4339                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4340                              <1> 
  4341                              <1> 	; / r1 contains the mode
  4342 00004C95 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4343                              <1> 		; bis $100000,r1 / allocate flag set
  4344 00004C98 6650                <1> 	push	ax ; * ; 24/12/2021
  4345                              <1> 		; mov r1,-(sp) / put mode on stack
  4346                              <1> 	; 31/07/2013
  4347 00004C9A 66A1[9C6E0000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4348                              <1> 		; mov ii,r1 / move current i-number to r1
  4349 00004CA0 B201                <1> 	mov	dl, 1 ; owner flag mask
  4350 00004CA2 E8C4050000          <1> 	call	access	
  4351                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4352 00004CA7 50                  <1> 	push	eax ; ** ; 24/12/2021
  4353                              <1> 		; mov r1,-(sp) / put i-number on stack
  4354 00004CA8 66B82800            <1> 	mov	ax, 40
  4355                              <1> 		; mov $40.,r1 / r1 = 40
  4356                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4357 00004CAC 6640                <1> 	inc	ax
  4358                              <1> 		; inc r1 / r1 = r1 + 1
  4359 00004CAE E87D060000          <1> 	call	imap
  4360                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4361                              <1> 			    ; /	inode map in r2 & m
  4362                              <1>   
  4363                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4364                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4365                              <1> 
  4366                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4367                              <1> 	;	       Inode count must be checked here
  4368                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4369                              <1> 
  4370                              <1> 	; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  4371                              <1> 	; (inode count check)
  4372                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4373                              <1> 
  4374 00004CB3 730F                <1> 	jnc	short maknod2
  4375                              <1> 
  4376                              <1> 	; no free inode in inode table !
  4377 00004CB5 C705[0D6F0000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4377 00004CBD 0000                <1>
  4378                              <1> 			; miscellaneous/other errors
  4379 00004CBF E910EEFFFF          <1> 	jmp	error	
  4380                              <1> maknod2: 
  4381 00004CC4 8413                <1> 	test	[ebx], dl
  4382                              <1> 		; bitb mq,(r2) / is the i-node active
  4383 00004CC6 75E4                <1> 	jnz	short maknod1
  4384                              <1> 		; bne 1b / yes, try the next one
  4385 00004CC8 0813                <1> 	or	[ebx], dl
  4386                              <1> 		; bisb mq,(r2) / no, make it active 
  4387                              <1> 			     ; / (put a 1 in the bit map)
  4388 00004CCA E8C8040000          <1> 	call	iget
  4389                              <1> 		; jsr r0,iget / get i-node into core
  4390                              <1> 	; 09/01/2022
  4391 00004CCF F605[B96B0000]80    <1> 	test	byte [i.flgs+1], 80h
  4392                              <1> 	;test	word [i.flgs], 8000h 
  4393                              <1> 		; tst i.flgs / is i-node already allocated
  4394 00004CD6 75D4                <1> 	jnz	short maknod1	
  4395                              <1> 		; blt 1b / yes, look for another one
  4396 00004CD8 66A3[EA6E0000]      <1> 	mov	[u.dirbuf], ax
  4397                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4398 00004CDE 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4399                              <1> 		; mov (sp)+,r1 / get current i-number back
  4400 00004CDF E8B3040000          <1> 	call	iget
  4401                              <1> 		; jsr r0,iget / get i-node in core
  4402 00004CE4 E8AFF7FFFF          <1> 	call	mkdir
  4403                              <1> 		; jsr r0,mkdir / make a directory entry 
  4404                              <1> 			     ; / in current directory
  4405 00004CE9 66A1[EA6E0000]      <1> 	mov	ax, [u.dirbuf]
  4406                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4407 00004CEF E8A3040000          <1> 	call	iget
  4408                              <1> 		; jsr r0,iget / get it into core
  4409                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4410                              <1> 	;mov	ecx, 8
  4411                              <1> 	; 09/01/2022 
  4412 00004CF4 29C9                <1> 	sub	ecx, ecx
  4413 00004CF6 B108                <1> 	mov	cl, 8
  4414 00004CF8 31C0                <1> 	xor	eax, eax ; 0
  4415 00004CFA BF[B86B0000]        <1> 	mov	edi, inode 
  4416 00004CFF F3AB                <1> 	rep	stosd
  4417                              <1> 	;
  4418 00004D01 668F05[B86B0000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4419                              <1> 		; mov (sp)+,i.flgs / fill flags
  4420 00004D08 8A0D[046F0000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4421 00004D0E 880D[BB6B0000]      <1> 	mov 	[i.uid], cl
  4422                              <1> 		; movb u.uid,i.uid / user id	
  4423 00004D14 C605[BA6B0000]01    <1> 	mov     byte [i.nlks], 1
  4424                              <1> 		; movb $1,i.nlks / 1 link
  4425                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4426                              <1> 	;mov	eax, [s.time]
  4427                              <1> 	;mov 	[i.ctim], eax
  4428                              <1> 	 	; mov s.time,i.ctim / time created
  4429                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4430                              <1> 	; Retro UNIX 8086 v1 modification !
  4431                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4432                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4433                              <1> 	;call	setimod
  4434                              <1> 	;	; jsr r0,setimod / set modified flag
  4435                              <1> 	;retn
  4436                              <1> 	;	; rts r0 / return
  4437                              <1> 	; 24/12/2021
  4438 00004D1B E981050000          <1> 	jmp	setimod
  4439                              <1> 
  4440                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4441                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4442                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4443                              <1> 	;
  4444                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4445                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4446                              <1> 	; The file descriptor refers to a file open for reading or
  4447                              <1> 	; writing. The read (or write) pointer is set as follows:
  4448                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4449                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4450                              <1> 	;	  current location plus offset.
  4451                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4452                              <1> 	;	  size of file plus offset.
  4453                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4454                              <1> 	;
  4455                              <1> 	; Calling sequence:
  4456                              <1> 	;	sysseek; offset; ptrname
  4457                              <1> 	; Arguments:
  4458                              <1> 	;	offset - number of bytes desired to move 
  4459                              <1> 	;		 the r/w pointer
  4460                              <1> 	;	ptrname - a switch indicated above
  4461                              <1> 	;
  4462                              <1> 	; Inputs: r0 - file descriptor 
  4463                              <1> 	; Outputs: -
  4464                              <1> 	; ...............................................................
  4465                              <1> 	;	
  4466                              <1> 	; Retro UNIX 8086 v1 modification: 
  4467                              <1> 	;       'sysseek' system call has three arguments; so,
  4468                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4469                              <1> 	;	* 2nd argument, offset is in CX register
  4470                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4471                              <1> 	;	
  4472                              <1> 
  4473 00004D20 E822000000          <1> 	call	seektell
  4474                              <1> 	; AX = u.count
  4475                              <1> 	; BX = *u.fofp
  4476                              <1> 		; jsr r0,seektell / get proper value in u.count
  4477                              <1> 		; add u.base,u.count / add u.base to it
  4478 00004D25 0305[D86E0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4479 00004D2B 8903                <1> 	mov	[ebx], eax
  4480                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4481 00004D2D E9C2EDFFFF          <1> 	jmp	sysret
  4482                              <1> 		; br sysret4
  4483                              <1> 
  4484                              <1> systell: ; / get the r/w pointer
  4485                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4486                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4487                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4488                              <1> 	;
  4489                              <1> 	; Retro UNIX 8086 v1 modification:
  4490                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4491                              <1> 	; 	    it returns with error !
  4492                              <1> 	; Inputs: r0 - file descriptor 
  4493                              <1> 	; Outputs: r0 - file r/w pointer
  4494                              <1> 
  4495                              <1> 	;xor	ecx, ecx ; 0
  4496                              <1> 	;mov	edx, 1 ; 05/08/2013
  4497                              <1> 	; 24/12/2021
  4498 00004D32 29D2                <1> 	sub	edx, edx
  4499 00004D34 FEC2                <1> 	inc	dl
  4500                              <1> 	; edx = 1
  4501                              <1> 	;call 	seektell
  4502 00004D36 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4503                              <1> 	;mov	ebx, [u.fofp]
  4504 00004D3B 8B03                <1> 	mov	eax, [ebx]
  4505 00004D3D A3[B86E0000]        <1> 	mov	[u.r0], eax
  4506 00004D42 E9ADEDFFFF          <1> 	jmp	sysret
  4507                              <1> 
  4508                              <1> ; Original unix v1 'systell' system call:
  4509                              <1> 		; jsr r0,seektell
  4510                              <1> 		; br error4
  4511                              <1> 
  4512                              <1> seektell:
  4513                              <1> 	; 03/02/2022
  4514                              <1> 	; 03/01/2016
  4515                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4516                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4517                              <1> 	;
  4518                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4519                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4520                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4521                              <1> 	; getf. The i-node is brought into core and then u.count
  4522                              <1> 	; is checked to see it is a 0, 1, or 2.
  4523                              <1> 	; If it is 0 - u.count stays the same
  4524                              <1> 	;          1 - u.count = offset (u.fofp)
  4525                              <1> 	;	   2 - u.count = i.size (size of file)
  4526                              <1> 	; 	 		
  4527                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4528                              <1> 	;	Argument 1, file descriptor is in BX;
  4529                              <1> 	;	Argument 2, offset is in CX;
  4530                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4531                              <1> 	;
  4532                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4533                              <1> 	; call 	arg
  4534                              <1> 	;
  4535                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4536                              <1> 	;
  4537 00004D47 890D[D86E0000]      <1> 	mov 	[u.base], ecx ; offset
  4538                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4539                              <1> seektell0:
  4540 00004D4D 8915[DC6E0000]      <1> 	mov 	[u.count], edx
  4541                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4542                              <1> 	; mov	ax, bx
  4543                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4544                              <1> 			     ; / (index in u.fp list)
  4545                              <1> 	; call	getf
  4546                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4547                              <1> 	; BX = file descriptor (file number)
  4548 00004D53 E849FCFFFF          <1> 	call	getf1
  4549                              <1> 	; 03/02/2022
  4550 00004D58 09C0                <1> 	or	eax, eax
  4551                              <1> 	;or	ax, ax ; i-number of the file
  4552                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4553                              <1> 		             ; / put it on the stack
  4554                              <1> 	;jz	error
  4555                              <1> 		; beq error4 / if i-number is 0, not active so error
  4556 00004D5A 750F                <1> 	jnz	short seektell1
  4557 00004D5C C705[0D6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4557 00004D64 0000                <1>
  4558 00004D66 E969EDFFFF          <1> 	jmp	error
  4559                              <1> seektell1:
  4560                              <1> 	;push	eax
  4561 00004D6B 80FC80              <1> 	cmp	ah, 80h
  4562 00004D6E 7203                <1> 	jb	short seektell2
  4563                              <1> 		; bgt .+4 / if its positive jump
  4564 00004D70 66F7D8              <1> 	neg	ax
  4565                              <1> 		; neg r1 / if not make it positive
  4566                              <1> seektell2:
  4567 00004D73 E81F040000          <1> 	call	iget
  4568                              <1> 		; jsr r0,iget / get its i-node into core
  4569 00004D78 8B1D[C86E0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4570 00004D7E 803D[DC6E0000]01    <1> 	cmp	byte [u.count], 1
  4571                              <1> 		; cmp u.count,$1 / is ptr name =1
  4572 00004D85 7705                <1> 	ja	short seektell3
  4573                              <1> 		; blt 2f / no its zero
  4574 00004D87 740A                <1> 	je	short seektell_4
  4575                              <1> 		; beq 1f / yes its 1
  4576 00004D89 31C0                <1> 	xor	eax, eax
  4577                              <1> 	;jmp	short seektell_5
  4578 00004D8B C3                  <1> 	retn
  4579                              <1> seektell3:
  4580                              <1> 	; 03/01/2016
  4581                              <1> 	;movzx	eax, word [i.size]
  4582 00004D8C 66A1[BC6B0000]      <1>         mov   	ax, [i.size]
  4583                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4584                              <1>                                    ; / in file in u.count
  4585                              <1> 	;jmp	short seektell_5
  4586                              <1> 		; br 2f
  4587 00004D92 C3                  <1> 	retn
  4588                              <1> seektell_4: ; 1: / ptrname =1
  4589                              <1> 	;mov	ebx, [u.fofp]
  4590 00004D93 8B03                <1> 	mov	eax, [ebx]
  4591                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4592                              <1> ;seektell_5: ; 2: / ptrname =0
  4593                              <1> 	;mov	[u.count], eax
  4594                              <1> 	;pop	eax 
  4595                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4596 00004D95 C3                  <1> 	retn
  4597                              <1> 		; rts r0
  4598                              <1> 
  4599                              <1> sysintr: ; / set interrupt handling
  4600                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4601                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4602                              <1> 	;
  4603                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4604                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4605                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4606                              <1> 	; If one does the interrupt character in the tty buffer is
  4607                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4608                              <1> 	; 'sysret' is just called.	
  4609                              <1> 	;
  4610                              <1> 	; Calling sequence:
  4611                              <1> 	;	sysintr; arg
  4612                              <1> 	; Argument:
  4613                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4614                              <1> 	;	    - if 1, intterupts cause their normal result
  4615                              <1> 	;		 i.e force an exit.
  4616                              <1> 	;	    - if arg is a location within the program,
  4617                              <1> 	;		control is passed to that location when
  4618                              <1> 	;		an interrupt occurs.	
  4619                              <1> 	; Inputs: -
  4620                              <1> 	; Outputs: -
  4621                              <1> 	; ...............................................................
  4622                              <1> 	;	
  4623                              <1> 	; Retro UNIX 8086 v1 modification: 
  4624                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4625                              <1> 	;	then branches into sysquit.
  4626                              <1> 	;
  4627 00004D96 66891D[FC6E0000]    <1> 	mov	[u.intr], bx
  4628                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4629                              <1> 		; br 1f / go into quit routine
  4630 00004D9D E952EDFFFF          <1> 	jmp	sysret
  4631                              <1> 
  4632                              <1> sysquit:
  4633                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4634                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4635                              <1> 	;
  4636                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4637                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4638                              <1> 	; tty exists. If one does the interrupt character in the tty
  4639                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4640                              <1> 	; 'sysret' is just called.	
  4641                              <1> 	;
  4642                              <1> 	; Calling sequence:
  4643                              <1> 	;	sysquit; arg
  4644                              <1> 	; Argument:
  4645                              <1> 	;	arg - if 0, this call diables quit signals from the
  4646                              <1> 	;		typewriter (ASCII FS)
  4647                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4648                              <1> 	;		cease and a core image to be produced.
  4649                              <1> 	;		 i.e force an exit.
  4650                              <1> 	;	    - if arg is an addres in the program,
  4651                              <1> 	;		a quit causes control to sent to that
  4652                              <1> 	;		location.	
  4653                              <1> 	; Inputs: -
  4654                              <1> 	; Outputs: -
  4655                              <1> 	; ...............................................................
  4656                              <1> 	;	
  4657                              <1> 	; Retro UNIX 8086 v1 modification: 
  4658                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4659                              <1> 	;	then branches into 'sysret'.
  4660                              <1> 	;
  4661 00004DA2 66891D[FE6E0000]    <1> 	mov	[u.quit], bx
  4662 00004DA9 E946EDFFFF          <1> 	jmp	sysret
  4663                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4664                              <1> 	;1:
  4665                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4666                              <1> 			      ; / to r1
  4667                              <1> 		; beq sysret4 / return to user
  4668                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4669                              <1> 			   ; / in the tty buffer
  4670                              <1> 		; br sysret4 / return to user
  4671                              <1> 
  4672                              <1> syssetuid: ; / set process id
  4673                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4674                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4675                              <1> 	;
  4676                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4677                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4678                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4679                              <1> 	; Only the super user can make this call.	
  4680                              <1> 	;
  4681                              <1> 	; Calling sequence:
  4682                              <1> 	;	syssetuid
  4683                              <1> 	; Arguments: -
  4684                              <1> 	;
  4685                              <1> 	; Inputs: (u.r0) - contains the process id.
  4686                              <1> 	; Outputs: -
  4687                              <1> 	; ...............................................................
  4688                              <1> 	;	
  4689                              <1> 	; Retro UNIX 8086 v1 modification: 
  4690                              <1> 	;       BL contains the (new) user ID of the current process
  4691                              <1> 
  4692                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4693 00004DAE 3A1D[056F0000]      <1> 	cmp	bl, [u.ruid] 
  4694                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4695                              <1> 			       ; / id number
  4696 00004DB4 741E                <1> 	je	short setuid1
  4697                              <1> 		; beq 1f / yes
  4698 00004DB6 803D[046F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4699                              <1> 		; tstb u.uid / no, is current user the super user?
  4700                              <1> 	;ja	error
  4701                              <1> 		; bne error4 / no, error
  4702 00004DBD 760F                <1> 	jna	short setuid0
  4703 00004DBF C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4703 00004DC7 0000                <1>
  4704                              <1> 				; 'permission denied !' error
  4705 00004DC9 E906EDFFFF          <1> 	jmp	error
  4706                              <1> setuid0:
  4707 00004DCE 881D[056F0000]      <1> 	mov	[u.ruid], bl
  4708                              <1> setuid1: ; 1:
  4709 00004DD4 881D[046F0000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4710                              <1> 		; movb r1,u.uid / put process id in u.uid
  4711                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4712 00004DDA E915EDFFFF          <1> 	jmp	sysret
  4713                              <1> 		; br sysret4 / system return
  4714                              <1> 
  4715                              <1> sysgetuid: ; < get user id >
  4716                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4717                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4718                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4719                              <1> 	;
  4720                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4721                              <1> 	; The real user ID identifies the person who is logged in,
  4722                              <1> 	; in contradistinction to the effective user ID, which
  4723                              <1> 	; determines his access permission at each moment. It is thus
  4724                              <1> 	; useful to programs which operate using the 'set user ID'
  4725                              <1> 	; mode, to find out who invoked them.	
  4726                              <1> 	;
  4727                              <1> 	; Calling sequence:
  4728                              <1> 	;	syssetuid
  4729                              <1> 	; Arguments: -
  4730                              <1> 	;
  4731                              <1> 	; Inputs: -
  4732                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4733                              <1> 	; ...............................................................
  4734                              <1> 	;	
  4735                              <1> 	; Retro UNIX 8086 v1 modification: 
  4736                              <1> 	;       AL contains the real user ID at return.
  4737                              <1> 	;
  4738                              <1> 	;movzx 	eax, byte [u.ruid]
  4739                              <1> 	; 09/01/2022
  4740 00004DDF A0[056F0000]        <1> 	mov	al, [u.ruid]
  4741 00004DE4 A3[B86E0000]        <1> 	mov	[u.r0], eax
  4742                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4743 00004DE9 E906EDFFFF          <1> 	jmp	sysret
  4744                              <1> 		; br sysret4 / systerm return, sysret
  4745                              <1> 
  4746                              <1> anyi: 
  4747                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4748                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4749                              <1> 	;
  4750                              <1> 	; 'anyi' is called if a file deleted while open.
  4751                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4752                              <1> 	;
  4753                              <1> 	; INPUTS ->
  4754                              <1> 	;    r1 - contains an i-number
  4755                              <1> 	;    fsp - start of table containing open files
  4756                              <1> 	;
  4757                              <1> 	; OUTPUTS ->
  4758                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4759                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4760                              <1> 	;    if file not found - bit in i-node map is cleared
  4761                              <1> 	;    			 (i-node is freed)
  4762                              <1> 	;               all blocks related to i-node are freed
  4763                              <1> 	;	        all flags in i-node are cleared
  4764                              <1> 	; ((AX = R1)) input
  4765                              <1> 	;
  4766                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4767                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4768                              <1> 	;
  4769                              <1> 		; / r1 contains an i-number
  4770 00004DEE BB[886C0000]        <1> 	mov	ebx, fsp
  4771                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4772                              <1> anyi_1: ; 1:
  4773 00004DF3 663B03              <1> 	cmp	ax, [ebx]
  4774                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4775 00004DF6 7433                <1> 	je	short anyi_3
  4776                              <1> 		; beq 1f / yes, 1f
  4777 00004DF8 66F7D8              <1> 	neg	ax
  4778                              <1> 		; neg r1 / no complement r1
  4779 00004DFB 663B03              <1> 	cmp	ax, [ebx]
  4780                              <1> 		; cmp r1,(r2) / do they match now?
  4781 00004DFE 742B                <1> 	je	short anyi_3
  4782                              <1> 		; beq 1f / yes, transfer
  4783                              <1> 		; / i-numbers do not match
  4784 00004E00 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4785                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4786                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4787 00004E03 81FB[7C6E0000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4788                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4789                              <1> 				; / are we at last entry in the table
  4790 00004E09 72E8                <1> 	jb	short anyi_1
  4791                              <1> 		; blt 1b / no, check next entries i-number
  4792                              <1> 	;cmp	ax, 32768
  4793 00004E0B 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4794                              <1> 		; tst r1 / yes, no match
  4795                              <1> 		; bge .+4
  4796 00004E0E 7203                <1> 	jb	short anyi_2
  4797 00004E10 66F7D8              <1> 	neg	ax
  4798                              <1> 		; neg r1 / make i-number positive
  4799                              <1> anyi_2:	
  4800 00004E13 E818050000          <1> 	call	imap
  4801                              <1> 		; jsr r0,imap / get address of allocation bit 
  4802                              <1> 			    ; / in the i-map in r2
  4803                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4804                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4805                              <1>  	; not	dx
  4806 00004E18 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4807                              <1>         ;and	[ebx], dx
  4808 00004E1A 2013                <1> 	and 	[ebx], dl 
  4809                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4810 00004E1C E8A2040000          <1> 	call	itrunc
  4811                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4812 00004E21 66C705[B86B0000]00- <1>  	mov 	word [i.flgs], 0
  4812 00004E29 00                  <1>
  4813                              <1> 		; clr i.flgs / clear all flags in the i-node
  4814 00004E2A C3                  <1> 	retn
  4815                              <1> 		;rts	r0 / return
  4816                              <1> anyi_3: ; 1: / i-numbers match
  4817 00004E2B FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4818                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4819                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4820 00004E2E C3                  <1> 	retn
  4821                              <1> 		; rts r0
  2090                                  %include 'u3.s'        ; 10/05/2015
  2091                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  2092                              <1> ; Last Modification: 24/12/2021
  2093                              <1> ; ----------------------------------------------------------------------------
  2094                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2095                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2096                              <1> ;
  2097                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2098                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2099                              <1> ; <Bell Laboratories (17/3/1972)>
  2100                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2101                              <1> ;
  2102                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2103                              <1> ;
  2104                              <1> ; ****************************************************************************
  2105                              <1> 
  2106                              <1> tswitch: ; Retro UNIX 386 v1
  2107                              <1> tswap:
  2108                              <1> 	; 01/09/2015
  2109                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2110                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2111                              <1> 	; time out swap, called when a user times out.
  2112                              <1> 	; the user is put on the low priority queue.
  2113                              <1> 	; This is done by making a link from the last user
  2114                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2115                              <1> 	; then he is swapped out.
  2116                              <1> 	;
  2117                              <1> 	; Retro UNIX 386 v1 modification ->
  2118                              <1> 	;       swap (software task switch) is performed by changing
  2119                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2120                              <1> 	;	as in Retro UNIX 8086 v1.
  2121                              <1> 	;
  2122                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2123                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2124                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2125                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2126                              <1> 	;	compatibles was using 1MB segmented memory 
  2127                              <1> 	;	in 8086/8088 times.
  2128                              <1> 	;
  2129                              <1> 	; INPUTS ->
  2130                              <1> 	;    u.uno - users process number
  2131                              <1> 	;    runq+4 - lowest priority queue
  2132                              <1> 	; OUTPUTS ->
  2133                              <1> 	;    r0 - users process number
  2134                              <1> 	;    r2 - lowest priority queue address
  2135                              <1> 	;
  2136                              <1> 	; ((AX = R0, BX = R2)) output
  2137                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2138                              <1> 	;
  2139 00004E2F A0[076F0000]        <1> 	mov 	al, [u.uno]
  2140                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2141                              <1> 		; mov  $runq+4,r2 
  2142                              <1> 			; / move lowest priority queue address to r2
  2143 00004E34 E8CD000000          <1>         call 	putlu
  2144                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2145                              <1> 		             ; / u.uno's user
  2146                              <1> 
  2147                              <1> switch: ; Retro UNIX 386 v1
  2148                              <1> swap:
  2149                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2150                              <1> 	; 02/09/2015
  2151                              <1> 	; 01/09/2015
  2152                              <1> 	; 31/08/2015
  2153                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2154                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2155                              <1> 	; 'swap' is routine that controls the swapping of processes
  2156                              <1> 	; in and out of core.
  2157                              <1> 	;
  2158                              <1> 	; Retro UNIX 386 v1 modification ->
  2159                              <1> 	;       swap (software task switch) is performed by changing
  2160                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2161                              <1> 	;	as in Retro UNIX 8086 v1.
  2162                              <1> 	;
  2163                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2164                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2165                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2166                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2167                              <1> 	;	compatibles was using 1MB segmented memory 
  2168                              <1> 	;	in 8086/8088 times.
  2169                              <1> 	;
  2170                              <1> 	; INPUTS ->
  2171                              <1> 	;    runq table - contains processes to run.
  2172                              <1> 	;    p.link - contains next process in line to be run.
  2173                              <1> 	;    u.uno - process number of process in core	
  2174                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2175                              <1> 	; OUTPUTS ->
  2176                              <1> 	;    (original unix v1 -> present process to its disk block)
  2177                              <1> 	;    (original unix v1 -> new process into core -> 
  2178                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2179                              <1> 	;	   for new process)
  2180                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2181                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2182                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2183                              <1> 	;	 for now, it will swap the process if there is not
  2184                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2185                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2186                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2187                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2188                              <1> 	;
  2189                              <1> 	;    u.pri -points to highest priority run Q.
  2190                              <1> 	;    r2 - points to the run queue.
  2191                              <1> 	;    r1 - contains new process number
  2192                              <1> 	;    r0 - points to place in routine or process that called
  2193                              <1> 	;	  swap all user parameters
  2194                              <1> 	;				
  2195                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2196                              <1> 	;
  2197                              <1> swap_0:
  2198                              <1> 		;mov $300,*$ps / processor priority = 6
  2199 00004E39 BE[AA6E0000]        <1> 	mov	esi, runq
  2200                              <1> 		; mov $runq,r2 / r2 points to runq table
  2201                              <1> swap_1: ; 1: / search runq table for highest priority process
  2202 00004E3E 668B06              <1> 	mov	ax, [esi]
  2203 00004E41 6621C0              <1> 	and 	ax, ax
  2204                              <1>        		; tst (r2)+ / are there any processes to run 
  2205                              <1> 			  ; / in this Q entry
  2206 00004E44 7507                <1> 	jnz	short swap_2
  2207                              <1>        		; bne 1f / yes, process 1f
  2208                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2209                              <1> 			       ; / to end of table
  2210                              <1> 		; bne 1b / if not at end, go back
  2211 00004E46 E8E0000000          <1> 	call	idle
  2212                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2213                              <1> 				       ; / all queues are empty
  2214 00004E4B EBF1                <1> 	jmp	short swap_1
  2215                              <1> 		; br swap
  2216                              <1> swap_2: ; 1:
  2217 00004E4D 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2218                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2219                              <1>  		; mov r2,u.pri / set present user to this run queue
  2220                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2221 00004E50 38E0                <1> 	cmp	al, ah
  2222                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2223                              <1> 			      ; / in this Q to be run
  2224 00004E52 740A                <1> 	je	short swap_3
  2225                              <1>        		; beq 1f / yes
  2226                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2227                              <1> 	;movzx	ebx, al
  2228 00004E54 8AA3[276C0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2229 00004E5A 8826                <1>        	mov	[esi], ah
  2230                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2231                              <1> 				       ; / in line into run queue
  2232 00004E5C EB05                <1> 	jmp	short swap_4
  2233                              <1>        		; br 2f
  2234                              <1> swap_3: ; 1:
  2235                              <1> 	;xor	dx, dx
  2236                              <1> 	; 24/12/2021
  2237 00004E5E 31D2                <1> 	xor	edx, edx
  2238 00004E60 668916              <1> 	mov	[esi], dx
  2239                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2240                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2241                              <1>       ; / in new process if required
  2242                              <1>        		; clr *$ps / clear processor status
  2243 00004E63 8A25[076F0000]      <1> 	mov 	ah, [u.uno]
  2244 00004E69 38C4                <1> 	cmp	ah, al
  2245                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2246                              <1> 			      ; / the process in core?
  2247 00004E6B 743B                <1>        	je	short swap_8
  2248                              <1>        		; beq 2f / yes, don't have to swap
  2249                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2250                              <1> 			   ; / (address in routine that called swap)
  2251                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2252                              <1> 	; 01/09/2015
  2253                              <1> 	;mov	[u.usp], esp
  2254                              <1>        		; mov sp,u.usp / save stack pointer
  2255                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2256                              <1> 			       ; / to the stack pointer
  2257 00004E6D 08E4                <1> 	or	ah, ah
  2258                              <1>        		; tstb u.uno / is the process # = 0
  2259 00004E6F 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2260                              <1> 		; beq 1f / yes, kill process by overwriting
  2261                              <1> 	; 02/09/2015
  2262 00004E71 8925[B46E0000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2263                              <1> 	;
  2264 00004E77 E834000000          <1> 	call	wswap
  2265                              <1> 		; jsr r0,wswap / write out core to disk
  2266                              <1> 	 ; 31/08/2015
  2267                              <1> 	;movzx	ebx, al ; New (running) process number
  2268 00004E7C EB1C                <1> 	jmp 	short swap_7
  2269                              <1> swap_6:
  2270                              <1> 	; 31/08/2015
  2271                              <1> 	; Deallocate memory pages belong to the process
  2272                              <1> 	; which is being terminated
  2273                              <1> 	; 14/05/2015 ('sysexit')
  2274                              <1>  	; Deallocate memory pages of the process
  2275                              <1> 	; (Retro UNIX 386 v1 modification !)
  2276                              <1> 	;
  2277                              <1> 	; movzx ebx, al
  2278 00004E7E 53                  <1> 	push	ebx
  2279 00004E7F A1[116F0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2280 00004E84 8B1D[156F0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2281 00004E8A E859E0FFFF          <1> 	call	deallocate_page_dir
  2282 00004E8F A1[086F0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2283 00004E94 E8E7E0FFFF          <1> 	call	deallocate_page
  2284 00004E99 5B                  <1> 	pop	ebx
  2285                              <1> swap_7: ;1: 
  2286                              <1> 	; 02/09/2015
  2287                              <1> 	; 31/08/2015
  2288                              <1> 	; 14/05/2015
  2289 00004E9A C0E302              <1> 	shl	bl, 2 ; * 4 
  2290 00004E9D 8B83[446C0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2291                              <1> 	;cli
  2292 00004EA3 E831000000          <1> 	call	rswap
  2293                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2294                              <1> 		; jsr r0,rswap / read new process into core
  2295                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2296                              <1> 			      ; / to his program to its normal
  2297                              <1> 	; 01/09/2015
  2298                              <1> 	;mov	esp, [u.usp]	
  2299                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2300                              <1> 			     ; / new process stack
  2301                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2302                              <1> 			     ; / that just got swapped in, left off.,
  2303                              <1> 			     ; / i.e., transfer control to new process
  2304                              <1> 	;sti
  2305                              <1> swap_8: ;2:
  2306                              <1> 	; RETRO UNIX 8086 v1 modification !
  2307 00004EA8 C605[FA6E0000]04    <1> 	mov	byte [u.quant], time_count 
  2308                              <1> 		; movb $30.,uquant / initialize process time quantum
  2309 00004EAF C3                  <1> 	retn
  2310                              <1> 		; rts r0 / return
  2311                              <1> 
  2312                              <1> wswap:  ; < swap out, swap to disk >
  2313                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2314                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2315                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2316                              <1> 	; appropriate disk area.
  2317                              <1> 	;
  2318                              <1> 	; Retro UNIX 386 v1 modification ->
  2319                              <1> 	;       User (u) structure content and the user's register content
  2320                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2321                              <1> 	;	saving 'u' structure and user registers for task switching).
  2322                              <1> 	;	u.usp - points to kernel stack address which contains
  2323                              <1> 	;		user's registers while entering system call.  
  2324                              <1> 	;	u.sp  - points to kernel stack address 
  2325                              <1> 	;		to return from system call -for IRET-.
  2326                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2327                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2328                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2329                              <1> 	;
  2330                              <1> 	; Retro UNIX 8086 v1 modification ->
  2331                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2332                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2333                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2334                              <1> 	;	compatibles was using 1MB segmented memory 
  2335                              <1> 	;	in 8086/8088 times.
  2336                              <1> 	;
  2337                              <1> 	; INPUTS ->
  2338                              <1> 	;    u.break - points to end of program
  2339                              <1> 	;    u.usp - stack pointer at the moment of swap
  2340                              <1> 	;    core - beginning of process program		
  2341                              <1> 	;    ecore - end of core 	
  2342                              <1> 	;    user - start of user parameter area		
  2343                              <1> 	;    u.uno - user process number	
  2344                              <1> 	;    p.dska - holds block number of process	
  2345                              <1> 	; OUTPUTS ->
  2346                              <1> 	;    swp I/O queue
  2347                              <1> 	;    p.break - negative word count of process 
  2348                              <1> 	;    r1 - process disk address	
  2349                              <1> 	;    r2 - negative word count
  2350                              <1> 	;
  2351                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2352                              <1> 	;
  2353                              <1> 	; INPUTS ->
  2354                              <1> 	;    u.uno - process number (to be swapped out)
  2355                              <1> 	; OUTPUTS ->
  2356                              <1> 	;    none
  2357                              <1> 	;
  2358                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2359                              <1> 	;
  2360 00004EB0 8B3D[086F0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2361 00004EB6 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2362 00004EBB BE[B06E0000]        <1> 	mov	esi, user ; active user (u) structure	
  2363 00004EC0 F3A5                <1> 	rep	movsd
  2364                              <1> 	;
  2365 00004EC2 8B35[B46E0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2366                              <1> 			     ;      points to user registers)
  2367 00004EC8 8B0D[B06E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2368                              <1> 			     ; (for IRET)
  2369                              <1> 			     ; [u.sp] -> EIP (user)
  2370                              <1> 			     ; [u.sp+4]-> CS (user)
  2371                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2372                              <1> 			     ; [u.sp+12] -> ESP (user)
  2373                              <1> 			     ; [u.sp+16] -> SS (user)	
  2374 00004ECE 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2375 00004ED0 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2376                              <1> 			     ; (for IRET) 	
  2377 00004ED3 C1E902              <1> 	shr	ecx, 2	     		
  2378 00004ED6 F3A5                <1> 	rep	movsd
  2379 00004ED8 C3                  <1> 	retn
  2380                              <1> 
  2381                              <1> 	; Original UNIX v1 'wswap' routine:
  2382                              <1> 	; wswap:
  2383                              <1> 		; mov *$30,u.emt / determines handling of emts
  2384                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2385                              <1> 				; / illegal instructions
  2386                              <1> 		; mov u.break,r2 / put process program break address in r2
  2387                              <1> 		; inc r2 / add 1 to it 
  2388                              <1> 		; bic $1,r2 / make it even
  2389                              <1> 		; mov r2,u.break / set break to an even location
  2390                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2391                              <1> 			     ; / at moment of swap in r3
  2392                              <1> 		; cmp r2,$core / is u.break less than $core
  2393                              <1> 		; blos 2f / yes
  2394                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2395                              <1>        		; bhis 2f / yes
  2396                              <1> 	; 1:
  2397                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2398                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2399                              <1> 		; bne 1b / no, keep packing
  2400                              <1> 	 	; br 1f / yes
  2401                              <1> 	; 2:
  2402                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2403                              <1> 	; 1:
  2404                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2405                              <1> 			   ; / (user up to end of stack gets written out)
  2406                              <1> 		; neg r2 / make it negative
  2407                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2408                              <1> 		; mov r2,swp+4 / word count
  2409                              <1> 		; movb u.uno,r1 / move user process number to r1
  2410                              <1> 		; asl r1 / x2 for index
  2411                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2412                              <1> 				     ; / into the p.break table
  2413                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2414                              <1> 				    ; /	for process to r1
  2415                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2416                              <1> 			     ; / (block number)
  2417                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2418                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2419                              <1> 	; 1:
  2420                              <1>        		; tstb swp+1 / is lt done writing?
  2421                              <1>        		; bne 1b / no, wait
  2422                              <1> 		; rts r0 / yes, return to swap
  2423                              <1> 
  2424                              <1> rswap:  ; < swap in, swap from disk >
  2425                              <1> 	; 15/09/2015
  2426                              <1> 	; 28/08/2015
  2427                              <1> 	; 14/05/2015
  2428                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2429                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2430                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2431                              <1> 	; from disk into core.
  2432                              <1> 	;
  2433                              <1> 	; Retro UNIX 386 v1 modification ->
  2434                              <1> 	;       User (u) structure content and the user's register content
  2435                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2436                              <1> 	;	saving 'u' structure and user registers for task switching).
  2437                              <1> 	;	u.usp - points to kernel stack address which contains
  2438                              <1> 	;		user's registers while entering system call.  
  2439                              <1> 	;	u.sp  - points to kernel stack address 
  2440                              <1> 	;		to return from system call -for IRET-.
  2441                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2442                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2443                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2444                              <1> 	;
  2445                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2446                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2447                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2448                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2449                              <1> 	;	compatibles was using 1MB segmented memory 
  2450                              <1> 	;	in 8086/8088 times.
  2451                              <1> 	;
  2452                              <1> 	; INPUTS ->
  2453                              <1> 	;    r1 - process number of process to be read in
  2454                              <1> 	;    p.break - negative of word count of process 
  2455                              <1> 	;    p.dska - disk address of the process		
  2456                              <1> 	;    u.emt - determines handling of emt's 	
  2457                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2458                              <1> 	; OUTPUTS ->
  2459                              <1> 	;    8 = (u.ilgins)
  2460                              <1> 	;    24 = (u.emt)
  2461                              <1> 	;    swp - bit 10 is set to indicate read 
  2462                              <1> 	;		(bit 15=0 when reading is done)	
  2463                              <1> 	;    swp+2 - disk block address
  2464                              <1> 	;    swp+4 - negative word count 	
  2465                              <1> 	;      ((swp+6 - address of user structure)) 
  2466                              <1> 	;
  2467                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2468                              <1> 	;
  2469                              <1> 	; INPUTS ->
  2470                              <1> 	;    AL	- new process number (to be swapped in)	 
  2471                              <1> 	; OUTPUTS ->
  2472                              <1> 	;    none
  2473                              <1> 	;
  2474                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2475                              <1> 	;
  2476                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2477 00004ED9 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2478 00004EDB B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2479 00004EE0 BF[B06E0000]        <1> 	mov	edi, user ; active user (u) structure	
  2480 00004EE5 F3A5                <1> 	rep	movsd
  2481 00004EE7 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2482 00004EE8 8B3D[B46E0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2483                              <1> 			     ;      points to user registers)
  2484 00004EEE 8B0D[B06E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2485                              <1> 			     ; (for IRET)
  2486                              <1> 			     ; [u.sp] -> EIP (user)
  2487                              <1> 			     ; [u.sp+4]-> CS (user)
  2488                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2489                              <1> 			     ; [u.sp+12] -> ESP (user)
  2490                              <1> 			     ; [u.sp+16] -> SS (user)		
  2491                              <1> 	; 28/08/2015
  2492 00004EF4 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2493 00004EF6 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2494                              <1> 			     ; (for IRET) 	
  2495 00004EF9 C1E902              <1> 	shr	ecx, 2	       		
  2496 00004EFC F3A5                <1> 	rep	movsd
  2497 00004EFE 8B25[B46E0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2498 00004F04 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2499 00004F05 C3                  <1> 	retn
  2500                              <1> 
  2501                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2502                              <1> 	;rswap:
  2503                              <1>        		; asl r1 / process number x2 for index
  2504                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2505                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2506                              <1>        		; bis $2000,swp / read
  2507                              <1>        		; jsr r0,ppoke / read it in 
  2508                              <1> 	; 1:
  2509                              <1>        		; tstb swp+1 / done
  2510                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2511                              <1>        		; mov u.emt,*$30 / yes move these
  2512                              <1>        		; mov u.ilgins,*$10 / back
  2513                              <1>        		; rts r0 / return
  2514                              <1> 
  2515                              <1> 	;unpack: ; / move stack back to its normal place
  2516                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2517                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2518                              <1> 		; blos 2f / yes, return
  2519                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2520                              <1> 			     ; / before swapping
  2521                              <1> 		; bhis 2f / yes, return
  2522                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2523                              <1> 		; add r3,r2
  2524                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2525                              <1> 	; 1:
  2526                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2527                              <1> 		; cmp r2,u.break / in core
  2528                              <1> 		; bne 1b
  2529                              <1> 	; 2:
  2530                              <1>        		; rts r0
  2531                              <1> 
  2532                              <1> putlu: 
  2533                              <1> 	; 12/09/2015
  2534                              <1> 	; 02/09/2015
  2535                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2536                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2537                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2538                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2539                              <1> 	; the last process on the queue to process in r1 by putting
  2540                              <1> 	; the process number in r1 into the last process's link.
  2541                              <1> 	;
  2542                              <1> 	; INPUTS ->
  2543                              <1> 	;    r1 - user process number
  2544                              <1> 	;    r2 - points to lowest priority queue 
  2545                              <1> 	;    p.dska - disk address of the process		
  2546                              <1> 	;    u.emt - determines handling of emt's 	
  2547                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2548                              <1> 	; OUTPUTS ->
  2549                              <1> 	;    r3 - process number of last process on the queue upon
  2550                              <1> 	;	  entering putlu
  2551                              <1> 	;    p.link-1 + r3 - process number in r1
  2552                              <1> 	;    r2 - points to lowest priority queue
  2553                              <1> 	;
  2554                              <1> 	; ((Modified registers: EDX, EBX)) 
  2555                              <1> 	;
  2556                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2557                              <1> 
  2558                              <1> 	; eBX = r2
  2559                              <1> 	; eAX = r1 (AL=r1b)
  2560                              <1> 
  2561 00004F06 BB[AA6E0000]        <1> 	mov	ebx, runq
  2562 00004F0B 0FB613              <1> 	movzx  	edx, byte [ebx]
  2563 00004F0E 43                  <1> 	inc	ebx
  2564 00004F0F 20D2                <1> 	and	dl, dl
  2565                              <1> 		; tstb (r2)+ / is queue empty?
  2566 00004F11 740A                <1>        	jz	short putlu_1
  2567                              <1> 		; beq 1f / yes, branch
  2568 00004F13 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2569                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2570                              <1> 			     ; / in r3
  2571 00004F15 8882[276C0000]      <1>        	mov	[edx+p.link-1], al
  2572                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2573                              <1> 			     ; / "last users" link
  2574 00004F1B EB03                <1> 	jmp	short putlu_2
  2575                              <1> 		; br 2f /
  2576                              <1> putlu_1: ; 1:
  2577 00004F1D 8843FF              <1> 	mov	[ebx-1], al
  2578                              <1>        		; movb r1,-1(r2) / user is only user; 
  2579                              <1> 			    ; / put process no. at beginning and at end
  2580                              <1> putlu_2: ; 2: 
  2581 00004F20 8803                <1> 	mov	[ebx], al
  2582                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2583                              <1> 			     ; / on the queue
  2584 00004F22 88C2                <1> 	mov	dl, al
  2585 00004F24 88B2[276C0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2586                              <1> 		; dec r2 / restore r2
  2587 00004F2A C3                  <1>         retn
  2588                              <1> 		; rts r0
  2589                              <1> 
  2590                              <1> ;copyz:
  2591                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2592                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2593                              <1> ;       mov     (r0)+,r1
  2594                              <1> ;       mov     (r0)+,r2
  2595                              <1> ;1:
  2596                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2597                              <1> ;       cmp     r1,r2 
  2598                              <1> ;       blo     1b
  2599                              <1> ;       mov     (sp)+,r2 / restore r2
  2600                              <1> ;       mov     (sp)+,r1 / restore r1
  2601                              <1> ;       rts     r0 
  2602                              <1> 
  2603                              <1> idle:
  2604                              <1> 	; 01/09/2015
  2605                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2606                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2607                              <1> 	; (idle & wait loop)
  2608                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2609                              <1> 	; idle procedure!
  2610                              <1>       	;
  2611                              <1>   	; 01/09/2015
  2612 00004F2B FB                  <1> 	sti
  2613                              <1>       	; 29/07/2013
  2614 00004F2C F4                  <1>       	hlt
  2615 00004F2D 90                  <1>       	nop ; 10/10/2013
  2616 00004F2E 90                  <1>       	nop
  2617 00004F2F 90                  <1>       	nop
  2618                              <1>       	; 23/10/2013
  2619 00004F30 90                  <1>       	nop
  2620 00004F31 90                  <1>       	nop
  2621 00004F32 90                  <1>       	nop
  2622 00004F33 90                  <1>       	nop
  2623 00004F34 C3                  <1>       	retn      
  2624                              <1> 
  2625                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2626                              <1> 	;clr *$ps / clear ps
  2627                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2628                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2629                              <1> 	;1 / wait for interrupt
  2630                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2631                              <1> 	;mov (sp)+,*$ps
  2632                              <1> 	;rts r0
  2633                              <1> 
  2634                              <1> clear:
  2635                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2636                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2637                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2638                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2639                              <1> 	; on the current device (cdev)
  2640                              <1> 	;	
  2641                              <1> 	; INPUTS ->
  2642                              <1> 	;    r1 - block number of block to be zeroed
  2643                              <1> 	;    cdev - current device number 
  2644                              <1> 	; OUTPUTS ->
  2645                              <1> 	;    a zeroed I/O buffer onto the current device
  2646                              <1> 	;    r1 - points to last entry in the I/O buffer
  2647                              <1> 	;
  2648                              <1> 	; ((AX = R1)) input/output
  2649                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2650                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2651                              <1> 
  2652 00004F35 E8AF0D0000          <1> 	call 	wslot
  2653                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2654                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2655 00004F3A 89DF                <1> 	mov	edi, ebx ; r5
  2656 00004F3C 89C2                <1> 	mov	edx, eax
  2657 00004F3E B980000000          <1> 	mov	ecx, 128
  2658                              <1> 		; mov $256.,r3
  2659 00004F43 31C0                <1> 	xor	eax, eax
  2660 00004F45 F3AB                <1> 	rep	stosd
  2661 00004F47 89D0                <1> 	mov	eax, edx
  2662                              <1> ; 1: 
  2663                              <1>        		; clr (r5)+ / zero data word in buffer
  2664                              <1>        		; dec r3
  2665                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2666                              <1> 	;call	dskwr
  2667                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2668                              <1>                              ; / block specified in r1
  2669                              <1> 	; eAX (r1) = block number
  2670                              <1> 	;retn
  2671                              <1> 		; rts r0
  2672                              <1> 	; 24/12/2021
  2673 00004F49 E9B70D0000          <1> 	jmp	dskwr
  2091                                  %include 'u4.s'        ; 15/04/2015
  2092                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC
  2093                              <1> ; Last Modification: 26/02/2022
  2094                              <1> ; ----------------------------------------------------------------------------
  2095                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2096                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2097                              <1> ;
  2098                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2099                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2100                              <1> ; <Bell Laboratories (17/3/1972)>
  2101                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2102                              <1> ;
  2103                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2104                              <1> ;
  2105                              <1> ; ****************************************************************************
  2106                              <1> 
  2107                              <1> ;setisp:
  2108                              <1>        ;mov     r1,-(sp)
  2109                              <1>        ;mov     r2,-(sp)
  2110                              <1>        ;mov     r3,-(sp)
  2111                              <1>        ;mov     clockp,-(sp)
  2112                              <1>        ;mov     $s.syst+2,clockp
  2113                              <1>        ;jmp     (r0)
  2114                              <1> 
  2115                              <1> clock: ; / interrupt from 60 cycle clock
  2116                              <1> 	
  2117                              <1> 	; 14/10/2015
  2118                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2119                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2120                              <1> 
  2121                              <1>        ;mov     r0,-(sp) / save r0
  2122                              <1>        ;tst     *$lks / restart clock?
  2123                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2124                              <1>        ;inc     (r0)
  2125                              <1>        ;bne     1f
  2126                              <1>        ;inc     -(r0)
  2127                              <1> ;1:
  2128                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2129                              <1>        ;inc     (r0)
  2130                              <1>        ;bne     1f
  2131                              <1>        ;inc     -(r0)
  2132                              <1> ;1:
  2133                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2134                              <1> 
  2135 00004F4E 803D[FA6E0000]00    <1> 	cmp	byte [u.quant], 0
  2136 00004F55 772C                <1> 	ja	short clk_1
  2137                              <1> 	;
  2138 00004F57 803D[AF6E0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2139 00004F5E 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2140 00004F60 803D[076F0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2141 00004F67 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2142 00004F69 66833D[FC6E0000]00  <1> 	cmp	word [u.intr], 0
  2143 00004F71 7616                <1> 	jna	short clk_2
  2144                              <1> clk_0:
  2145                              <1> 	; 14/10/2015
  2146 00004F73 FE05[AF6E0000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2147 00004F79 58                  <1> 	pop	eax ; return address to the timer interrupt
  2148                              <1> 	;
  2149 00004F7A B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2150                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2151 00004F7C E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2152                              <1> 	;
  2153 00004F7E E9D6EBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2154                              <1> clk_1:
  2155 00004F83 FE0D[FA6E0000]      <1> 	dec	byte [u.quant]
  2156                              <1> clk_2:
  2157 00004F89 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2158                              <1> 
  2159                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2160                              <1> 
  2161                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2162                              <1>        ;decb    (r0)
  2163                              <1>        ;bge     1f / if less than 0
  2164                              <1>        ;clrb    (r0) / make it 0
  2165                              <1> ;1: / decrement time out counts return now if priority was not 0
  2166                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2167                              <1>        ;bge     2f / yes, check time outs
  2168                              <1>        ;tstb    (r0) / no, user timed out?
  2169                              <1>        ;bne     1f / no
  2170                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2171                              <1>        ;bne     1f / no, 1f
  2172                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2173                              <1>        ;sys     0 / sysrele
  2174                              <1>        ;rti
  2175                              <1> ;2: / priority is high so just decrement time out counts
  2176                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2177                              <1> ;2:
  2178                              <1>        ;tstb    (r0) / is the time out?
  2179                              <1>        ;beq     3f / yes, 3f (get next entry)
  2180                              <1>        ;decb    (r0) / no, decrement the time
  2181                              <1>        ;bne     3f / isit zero now?
  2182                              <1>        ;incb    (r0) / yes, increment the time
  2183                              <1> ;3:
  2184                              <1>        ;inc     r0 / next entry
  2185                              <1>        ;cmp     r0,$touts / end of toutt table?
  2186                              <1>        ;blo     2b / no, check this entry
  2187                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2188                              <1>        ;rti / return from interrupt
  2189                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2190                              <1>        ;mov     (sp)+,r0 / restore r0
  2191                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2192                              <1>        ;jsr     r0,setisp / save registers
  2193                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2194                              <1>                                ;  / the table
  2195                              <1> ;1:
  2196                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2197                              <1>        ;beq     2f / yes
  2198                              <1>        ;decb    toutt(r0) / no, decrement the time
  2199                              <1>        ;bne     2f / is the time 0, now
  2200                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2201                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2202                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2203                              <1> ;2:
  2204                              <1>        ;dec     r0 / set up r0 for next entry
  2205                              <1>        ;bge     1b / finished? , no, go back
  2206                              <1>        ;br      retisp / yes, restore registers and do a rti
  2207                              <1> 
  2208                              <1> ;retisp:
  2209                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2210                              <1>        ;mov     (sp)+,r3
  2211                              <1>        ;mov     (sp)+,r2
  2212                              <1>        ;mov     (sp)+,r1
  2213                              <1>        ;mov     (sp)+,r0
  2214                              <1>        ;rti     / return from interrupt
  2215                              <1> 
  2216                              <1> 
  2217                              <1> wakeup: ; / wakeup processes waiting for an event 
  2218                              <1> 	; / by linking them to the queue
  2219                              <1> 	;
  2220                              <1> 	; 26/02/2022
  2221                              <1> 	; 15/09/2015
  2222                              <1> 	; 29/06/2015
  2223                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2224                              <1> 	;
  2225                              <1> 	; 15/05/2013 - 02/06/2014
  2226                              <1> 	; Retro UNIX 8086 v1 modification !
  2227                              <1> 	; (Process/task switching routine by using
  2228                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2229                              <1> 	;
  2230                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2231                              <1> 	; sleeping in the specified wait channel by creating a link 
  2232                              <1> 	; to it from the last user process on the run queue.
  2233                              <1> 	; If there is no process to wake up, nothing happens.
  2234                              <1> 	;
  2235                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2236                              <1> 	; 'switching' status of the current process (owns current tty)
  2237                              <1> 	; (via alt + function keys) to a process which has highest
  2238                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2239                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2240                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2241                              <1> 	; tty for tty switching by keyboard.)	 
  2242                              <1> 	; 
  2243                              <1> 	; INPUT -> 
  2244                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2245                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2246                              <1> 	;
  2247                              <1> 	; ((modified registers: EAX, EBX))
  2248                              <1> 	;
  2249 00004F8A 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2250 00004F8D 81C3[586B0000]      <1> 	add	ebx, wlist
  2251 00004F93 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2252 00004F95 20C0                <1> 	and	al, al
  2253 00004F97 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2254                              <1> 	;
  2255 00004F99 30E4                <1> 	xor	ah, ah
  2256 00004F9B 8825[FA6E0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2257 00004FA1 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2258                              <1> 	; 15/09/2015
  2259 00004FA3 0FB6D8              <1> 	movzx	ebx, al
  2260                              <1> 	; 26/02/2022 (p.waitc is not used)
  2261                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2262 00004FA6 FEC4                <1> 	inc	ah
  2263 00004FA8 88A3[376C0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2264                              <1> 	;
  2265 00004FAE 57                  <1> 	push	edi
  2266 00004FAF 52                  <1> 	push	edx
  2267 00004FB0 E851FFFFFF          <1> 	call	putlu
  2268 00004FB5 5A                  <1> 	pop	edx
  2269 00004FB6 5F                  <1> 	pop	edi
  2270                              <1> wa0:
  2271 00004FB7 C3                  <1> 	retn
  2272                              <1> 
  2273                              <1> sleep: 
  2274                              <1> 	; 26/02/2022
  2275                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2276                              <1> 	; 15/09/2015
  2277                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2278                              <1> 	;
  2279                              <1> 	; 09/05/2013 - 20/03/2014
  2280                              <1> 	;
  2281                              <1> 	; Retro UNIX 8086 v1 modification !
  2282                              <1> 	; (Process/task switching and quit routine by using
  2283                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2284                              <1> 	;
  2285                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2286                              <1> 	; tty and tape output or input becomes available
  2287                              <1> 	; and process is put on waiting channel and swapped out,
  2288                              <1> 	; then -when the tty or tape is ready to write or read-
  2289                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2290                              <1> 	;
  2291                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2292                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2293                              <1> 	; status of the current process also INT 1Ch will count down
  2294                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2295                              <1> 	; to tty buffer of the current process and kernel will get
  2296                              <1> 	; user input by using tty buffer of the current process
  2297                              <1> 	; (instead of standard INT 16h interrupt).
  2298                              <1> 	; TTY output will be redirected to related video page of text mode
  2299                              <1> 	; (INT 10h will be called with different video page depending
  2300                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2301                              <1> 	; pseudo screens.)
  2302                              <1> 	;
  2303                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2304                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2305                              <1> 	; characters/data on serial port(s).
  2306                              <1> 	;
  2307                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2308                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2309                              <1> 	; 
  2310                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2311                              <1> 	;
  2312                              <1> 	;; 05/10/2013
  2313                              <1>         ;10/12/2013
  2314                              <1> 	;cmp   byte [u.uno], 1
  2315                              <1>         ;ja    short sleep0
  2316                              <1> 	;retn
  2317                              <1> 
  2318                              <1> 	; 20/03/2014
  2319                              <1> 	;mov	bx, [runq]
  2320                              <1> 	;cmp	bl, bh
  2321                              <1> 	;jne	short sleep0	
  2322                              <1> 	; 25/02/2014
  2323                              <1> 	;cmp word ptr [runq], 0
  2324                              <1> 	;ja short sleep0	
  2325                              <1> 	;retn
  2326                              <1> sleep0:
  2327                              <1> 	;
  2328 00004FB8 E849000000          <1> 	call	isintr
  2329                              <1> 	;jnz	sysret
  2330                              <1> 		; / wait for event
  2331                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2332                              <1> 			      ; / or quit from user
  2333                              <1>                		; br 2f / something happened
  2334                              <1> 			      ; / yes, his interrupt so return
  2335                              <1>                      	      ;	/ to user
  2336                              <1> 	; 24/12/2021
  2337 00004FBD 7405                <1> 	jz	short sleep_2
  2338                              <1> sleep_3:
  2339 00004FBF E930EBFFFF          <1> 	jmp	sysret
  2340                              <1> sleep_2:
  2341                              <1> 	; 30/06/2015
  2342 00004FC4 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2343 00004FC7 81C3[586B0000]      <1> 	add	ebx, wlist
  2344 00004FCD 8A03                <1> 	mov	al, [ebx]
  2345 00004FCF 20C0                <1> 	and	al, al
  2346 00004FD1 7407                <1> 	jz	short sleep1
  2347 00004FD3 53                  <1> 	push	ebx
  2348 00004FD4 E82DFFFFFF          <1> 	call	putlu
  2349 00004FD9 5B                  <1> 	pop	ebx
  2350                              <1> sleep1:
  2351 00004FDA A0[076F0000]        <1> 	mov	al, [u.uno]    
  2352 00004FDF 8803                <1>   	mov	[ebx], al 	; put the process number
  2353                              <1> 				; in the wait channel
  2354                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2355                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2356                              <1> 				     ; / on the stack
  2357                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2358                              <1> 				     ; / to put to sleep in there
  2359                              <1>         ; 15/09/2015
  2360 00004FE1 0FB6D8              <1> 	movzx	ebx, al
  2361 00004FE4 C683[376C0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2362                              <1> 	; 26/02/2022 (p.waitc is not used)
  2363                              <1> 	;inc	ah
  2364                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2365                              <1> 	;
  2366 00004FEB 66FF35[9F6E0000]    <1> 	push    word [cdev]
  2367                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2368 00004FF2 E842FEFFFF          <1> 	call	swap
  2369                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2370 00004FF7 668F05[9F6E0000]    <1>         pop     word [cdev]
  2371                              <1> 		; mov (sp)+,cdev / restore device
  2372 00004FFE E803000000          <1> 	call	isintr
  2373                              <1> 	; 22/09/2013
  2374                              <1> 	;jnz	sysret         
  2375                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2376                              <1>                		; br 2f / yes, return to new user
  2377                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2378                              <1> 				; / originally on the wait channel
  2379                              <1>        		; beq 1f / if 0 branch
  2380                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2381                              <1>        		; mov $300,*$ps / processor priority = 6
  2382                              <1> 		; jsr r0,putlu / create link to old process number
  2383                              <1>        		; clr *$ps / clear the status; process priority = 0
  2384                              <1> 	; 24/12/2021
  2385 00005003 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2386                              <1>      ;1:
  2387 00005005 C3                  <1> 	retn
  2388                              <1> 		; rts r0 / return
  2389                              <1>      ;2:
  2390                              <1>         ;;jmp	sysret
  2391                              <1> 		; jmp sysret / return to user
  2392                              <1> 
  2393                              <1> isintr:
  2394                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2395                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2396                              <1> 	;
  2397                              <1> 	; 09/05/2013 - 30/05/2014
  2398                              <1> 	;
  2399                              <1> 	; Retro UNIX 8086 v1 modification !
  2400                              <1> 	; (Process/task switching and quit routine by using
  2401                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2402                              <1> 	;
  2403                              <1> 	; Retro UNIX 8086 v1 modification:
  2404                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2405                              <1> 	;  and there is a 'quit' request by user;
  2406                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2407                              <1> 	;  "nothing to do". (20/10/2013)
  2408                              <1> 	;
  2409                              <1> 	; 20/10/2013
  2410 00005006 66833D[E86E0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2411 0000500E 761F                <1> 	jna	short isintr2 ; retn
  2412                              <1> 	; 03/09/2013
  2413                              <1> 	; (nothing to do)
  2414                              <1> 	;retn
  2415                              <1> 	; 22/09/2013
  2416 00005010 66833D[FC6E0000]00  <1> 	cmp	word [u.intr], 0
  2417 00005018 7615                <1> 	jna	short isintr2 ; retn
  2418                              <1> 	; 30/05/2014
  2419                              <1> 	;push	ax
  2420                              <1> 	; 24/12/2021
  2421 0000501A 50                  <1> 	push	eax
  2422 0000501B 66A1[FE6E0000]      <1> 	mov	ax, [u.quit]
  2423 00005021 6609C0              <1> 	or	ax, ax ; 0 ?
  2424 00005024 7408                <1> 	jz	short isintr1 ; zf = 1
  2425 00005026 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2426 0000502A 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2427                              <1> 	;xor	ax, ax ; zf = 1
  2428                              <1> 	; 24/12/2021
  2429 0000502C 31C0                <1> 	xor	eax, eax ; zf = 1
  2430                              <1> isintr1:
  2431                              <1> 	;pop	ax
  2432                              <1> 	; 24/12/2021
  2433 0000502E 58                  <1> 	pop	eax
  2434                              <1> isintr2: ; 22/09/2013
  2435                              <1> 	; zf=1 -> nothing to do
  2436 0000502F C3                  <1> 	retn
  2437                              <1> 
  2438                              <1> 	; UNIX v1 original 'isintr' routine... 
  2439                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2440                              <1>        	;mov     r2,-(sp) / save r2
  2441                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2442                              <1>         ;                 / typewriter
  2443                              <1>        	;beq     1f / if 0, do nothing except skip return
  2444                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2445                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2446                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2447                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2448                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2449                              <1>         ;              / of interrupts
  2450                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2451                              <1>      ;1:
  2452                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2453                              <1>      ;4:
  2454                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2455                              <1>        	;mov     (sp)+,r1
  2456                              <1>        	;rts     r0
  2457                              <1>      ;3: / interrupt char = quit (fs)
  2458                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2459                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2460                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2461                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2462                              <1>      ;1: / find process control tty entry in tty block
  2463                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2464                              <1>        	;beq     1f / block found go to 1f
  2465                              <1>        	;add     $8,r1 / look at next tty block
  2466                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2467                              <1>        	;blo     1b / no
  2468                              <1>        	;br      4b / no process control tty found so go to 4b
  2469                              <1>      ;1:
  2470                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2471                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2472                              <1>         ;                  / identifier
  2473                              <1>        	;inc     0f / increment
  2474                              <1>      ;1:
  2475                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2476                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2477                              <1>         ;             / being typed out after you hit the interrupt
  2478                              <1>         ;             / key
  2479                              <1>        	;br      1b
  2092                                  %include 'u5.s'        ; 03/06/2015
  2093                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC
  2094                              <1> ; Last Modification: 11/02/2022
  2095                              <1> ; ----------------------------------------------------------------------------
  2096                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2097                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2098                              <1> ;
  2099                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2100                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2101                              <1> ; <Bell Laboratories (17/3/1972)>
  2102                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2103                              <1> ;
  2104                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2105                              <1> ;
  2106                              <1> ; ****************************************************************************
  2107                              <1> 
  2108                              <1> mget:
  2109                              <1> 	; 09/01/2022
  2110                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2111                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2112                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2113                              <1> 	;
  2114                              <1> 	; Get existing or (allocate) a new disk block for file
  2115                              <1> 	; 
  2116                              <1> 	; INPUTS ->
  2117                              <1> 	;    u.fofp (file offset pointer)
  2118                              <1> 	;    inode 
  2119                              <1> 	;    u.off (file offset)
  2120                              <1> 	; OUTPUTS ->
  2121                              <1> 	;    r1 (physical block number)
  2122                              <1> 	;    r2, r3, r5 (internal)
  2123                              <1> 	;
  2124                              <1> 	; ((AX = R1)) output
  2125                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2126                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2127                              <1> 
  2128                              <1> 		; mov *u.fofp,mq / file offset in mq
  2129                              <1> 		; clr ac / later to be high sig
  2130                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2131                              <1> 		; mov mq,r2
  2132                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2133                              <1> 		; bne 4f / branch for large file
  2134                              <1> mget_0:	
  2135                              <1> 	; 09/01/2022
  2136 00005030 29C0                <1> 	sub	eax, eax
  2137 00005032 29D2                <1> 	sub	edx, edx
  2138 00005034 29C9                <1> 	sub	ecx, ecx
  2139 00005036 29DB                <1> 	sub	ebx, ebx
  2140                              <1> 
  2141 00005038 8B35[C86E0000]      <1>         mov     esi, [u.fofp]
  2142                              <1>         ;movzx	ebx, byte [esi+1]
  2143                              <1> 	; 09/01/2022
  2144 0000503E 46                  <1> 	inc	esi
  2145 0000503F 8A1E                <1> 	mov	bl, [esi]
  2146                              <1> 
  2147                              <1> 	; BX = r2
  2148                              <1>         ; 24/12/2021
  2149 00005041 F605[B96B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2150                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2151                              <1> 				  ; is this a large or small file
  2152 00005048 756A                <1> 	jnz 	short mget_5 ; 4f ; large file
  2153                              <1> 
  2154 0000504A F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2155                              <1> 		; bit $!17,r2
  2156 0000504D 7525                <1> 	jnz 	short mget_2
  2157                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2158 0000504F 80E30E              <1>         and     bl, 0Eh  
  2159                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2160                              <1> 	; 09/01/2021
  2161 00005052 668B83[BE6B0000]    <1> 	mov	ax, [ebx+i.dskp]
  2162                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2163                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2164                              <1> 	; 24/12/2021
  2165 00005059 09C0                <1> 	or	eax, eax
  2166                              <1> 	;or 	ax, ax
  2167 0000505B 7516                <1> 	jnz 	short mget_1 
  2168                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2169                              <1> 		       ; / for file
  2170 0000505D E8A4000000          <1> 	call 	alloc
  2171                              <1> 		; jsr r0,alloc / allocate a new block
  2172                              <1>          ; eAX (r1) = Physical block number
  2173 00005062 668983[BE6B0000]    <1> 	mov 	[ebx+i.dskp], ax
  2174                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2175 00005069 E833020000          <1> 	call 	setimod	
  2176                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2177 0000506E E8C2FEFFFF          <1> 	call	clear
  2178                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2179                              <1> mget_1: ; 2:
  2180                              <1>         ; eAX (r1) = Physical block number
  2181 00005073 C3                  <1> 	retn 
  2182                              <1> 		; rts r0
  2183                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2184 00005074 E88D000000          <1> 	call 	alloc
  2185                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2186                              <1> 	                     ; / block number in r1
  2187                              <1>         ; eAX (r1) = Physical block number
  2188 00005079 E86B0C0000          <1> 	call 	wslot
  2189                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2190                              <1> 			     ; / first data word in buffer
  2191                              <1>         ; eAX (r1) = Physical block number
  2192                              <1> 	; 09/01/2022
  2193 0000507E 31C9                <1> 	xor	ecx, ecx
  2194 00005080 B108                <1> 	mov	cl, 8
  2195                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2196                              <1> 		   ; into new indirect block area for the new
  2197                              <1> 		   ; large file		
  2198 00005082 89DF                <1> 	mov 	edi, ebx ; r5
  2199 00005084 BE[BE6B0000]        <1> 	mov 	esi, i.dskp 
  2200                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2201                              <1> 			   ; / block pointers
  2202                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2203                              <1> 			  ; / large file
  2204                              <1> 	;xor 	ax, ax ; mov ax, 0
  2205                              <1> 	; 24/12/2021
  2206 00005089 31C0                <1> 	xor	eax, eax
  2207                              <1> mget_3: ;1:
  2208 0000508B 66A5                <1> 	movsw
  2209                              <1> 		; mov (r2),(r5)+
  2210 0000508D 668946FE            <1> 	mov 	[esi-2], ax
  2211                              <1> 		; clr (r2)+
  2212 00005091 E2F8                <1> 	loop	mget_3 ; 1b
  2213                              <1> 		; dec r3
  2214                              <1> 		; bgt 1b
  2215                              <1> 
  2216 00005093 B1F8                <1> 	mov 	cl, 256-8
  2217                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2218                              <1> mget_4:	; 1
  2219 00005095 F366AB              <1> 	rep 	stosw
  2220                              <1> 		; clr (r5)+
  2221                              <1> 		; dec r3
  2222                              <1> 		; bgt 1b
  2223                              <1> 	; 24/03/2013
  2224                              <1>         ; AX (r1) = Physical block number
  2225 00005098 E8680C0000          <1> 	call	dskwr
  2226                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2227                              <1>         ; eAX (r1) = Physical block number
  2228 0000509D 66A3[BE6B0000]      <1> 	mov 	[i.dskp], ax
  2229                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2230                              <1> 	; 09/01/2022
  2231 000050A3 800D[B96B0000]10    <1> 	or	byte [i.flgs+1], 10h
  2232                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2233                              <1> 		; bis $10000,i.flgs / set large file bit 
  2234                              <1> 				  ; / in i.flgs word of i-node
  2235 000050AA E8F2010000          <1> 	call	setimod
  2236                              <1> 		; jsr r0,setimod / set i-node modified flag
  2237 000050AF E97CFFFFFF          <1>         jmp     mget_0 
  2238                              <1> 		; br mget
  2239                              <1> 
  2240                              <1> mget_5:  ; 4 ; large file
  2241                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2242                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2243                              <1> 			    ; / in indirect block
  2244                              <1> 		; mov r2,-(sp) / save on stack (*)
  2245                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2246                              <1>        		          ; / indirect block
  2247                              <1> 		; bic $!16,r2
  2248 000050B4 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2249 000050B7 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2250                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2251                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2252                              <1> 	; There is always 1 indirect block for this file system
  2253                              <1> 	; 09/01/2022
  2254 000050B8 66A1[BE6B0000]      <1> 	mov	ax, [i.dskp]
  2255                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2256                              <1> 		; mov i.dskp(r2),r1
  2257                              <1> 	; 09/01/2022
  2258 000050BE 09C0                <1> 	or	eax, eax
  2259                              <1> 	;or 	ax, ax ; R1
  2260 000050C0 7515                <1> 	jnz 	short mget_6 ; 2f
  2261                              <1> 		; bne 2f / if no indirect block exists
  2262 000050C2 E83F000000          <1> 	call 	alloc
  2263                              <1> 		; jsr r0,alloc / allocate a new block
  2264 000050C7 66A3[BE6B0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2265                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2266 000050CD E8CF010000          <1> 	call 	setimod
  2267                              <1> 		; jsr r0,setimod / set i-node modified byte
  2268                              <1> 	; eAX = new block number
  2269 000050D2 E85EFEFFFF          <1> 	call 	clear
  2270                              <1> 		; jsr r0,clear / clear new block
  2271                              <1> mget_6: ;2
  2272                              <1> 	; 05/03/2013
  2273                              <1> 	; eAX = r1, physical block number (of indirect block)
  2274 000050D7 E89B0B0000          <1> 	call 	dskrd ; read indirect block
  2275                              <1> 		; jsr r0,dskrd / read in indirect block
  2276 000050DC 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2277                              <1> 		; mov (sp)+,r2 / get offset
  2278                              <1> 	; eAX = r1, physical block number (of indirect block)
  2279 000050DD 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2280                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2281                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2282 000050DE 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2283                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2284                              <1> 	                  ; / points to location of inter
  2285                              <1> 	; 09/01/2022
  2286 000050E0 668B03              <1> 	mov	ax, [ebx]
  2287                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2288                              <1> 			      ; in file sought in R1 (AX)
  2289                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2290                              <1> 	               	    ; / sought in r1
  2291                              <1> 	; 09/01/2022
  2292 000050E3 09C0                <1> 	or	eax, eax
  2293                              <1> 	;or 	ax, ax
  2294 000050E5 751D                <1>         jnz 	short mget_7 ; 2f
  2295                              <1> 		; bne 2f / if no block exists 
  2296 000050E7 E81A000000          <1> 	call 	alloc
  2297                              <1> 		; jsr r0,alloc / allocate a new block
  2298 000050EC 668903              <1> 	mov 	[ebx], ax ; R1
  2299                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2300                              <1> 	                    ; / indirect block
  2301 000050EF 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2302                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2303 000050F0 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2304 000050F1 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2305 000050F2 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2306                              <1> 		; mov (r2),-(sp) / save block number of new block
  2307                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2308 000050F4 E8F00B0000          <1> 	call 	wslot
  2309                              <1> 		; jsr r0,wslot
  2310                              <1>         ; eAX (r1) = physical block number
  2311                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2312 000050F9 E8070C0000          <1> 	call 	dskwr
  2313                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2314                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2315                              <1> 			     ; / back out on disk
  2316 000050FE 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2317                              <1> 		; mov (sp),r1 / restore block number of new block	
  2318                              <1> 	; eAX (r1) = physical block number of new block
  2319 000050FF E831FEFFFF          <1> 	call 	clear
  2320                              <1> 		; jsr r0,clear / clear new block	
  2321                              <1> mget_7: ; 2
  2322 00005104 5A                  <1> 	pop 	edx ; **
  2323                              <1> 		; tst (sp)+ / bump stack pointer
  2324                              <1> 	; eAX (r1) = Block number of new block
  2325 00005105 C3                  <1> 	retn
  2326                              <1> 		; rts r0
  2327                              <1> 
  2328                              <1> alloc:
  2329                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2330                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2331                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2332                              <1> 	;
  2333                              <1> 	; get a free block and 
  2334                              <1> 	; set the corresponding bit in the free storage map
  2335                              <1> 	; 
  2336                              <1> 	; INPUTS ->
  2337                              <1> 	;    cdev (current device)
  2338                              <1> 	;    r2 
  2339                              <1> 	;    r3
  2340                              <1> 	; OUTPUTS ->
  2341                              <1> 	;    r1 (physical block number of block assigned)
  2342                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2343                              <1> 	;
  2344                              <1> 	; ((AX = R1)) output
  2345                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2346                              <1>         ;    ((Modified registers: DX, CX))  
  2347                              <1> 
  2348                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2349                              <1> 		;mov r3,-(sp)
  2350                              <1> 	;push 	ecx
  2351 00005106 53                  <1> 	push 	ebx ; R2
  2352                              <1> 	;push 	edx ; R3
  2353 00005107 BB[787B0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2354                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2355 0000510C 803D[9F6E0000]00    <1> 	cmp 	byte [cdev], 0
  2356                              <1> 		; tst cdev
  2357 00005113 7605                <1> 	jna	short alloc_1
  2358                              <1> 		; beq 1f / drum is device
  2359 00005115 BB[807D0000]        <1> 	mov	ebx, mount
  2360                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2361                              <1> 			      ; / free storage map
  2362                              <1> alloc_1: ; 1
  2363                              <1> 	; 09/01/2022
  2364                              <1> 	;sub	ecx, ecx
  2365                              <1> 	;sub	edx, edx
  2366                              <1> 	;sub	eax, eax
  2367                              <1> 
  2368 0000511A 668B0B              <1>         mov	cx, [ebx]
  2369                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2370                              <1> 			     ; / storage map
  2371                              <1> 	; 09/01/2022
  2372 0000511D C1E103              <1> 	shl	ecx, 3
  2373                              <1> 	;shl	cx, 3
  2374                              <1> 		; asl r1 / multiply r1 by eight gives 
  2375                              <1> 		; number of blocks in device
  2376                              <1> 		; asl r1
  2377                              <1> 		; asl r1
  2378                              <1> 	;;push	cx ;; 01/08/2013
  2379                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2380 00005120 31C0                <1> 	xor 	eax, eax ; 0
  2381                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2382                              <1> alloc_2: ; 1
  2383 00005122 43                  <1> 	inc 	ebx ; 18/8/2012
  2384 00005123 43                  <1> 	inc 	ebx ; 
  2385 00005124 668B13              <1> 	mov 	dx, [ebx]
  2386                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2387                              <1> 	; 09/01/2022
  2388 00005127 09D2                <1> 	or	edx, edx
  2389                              <1> 	;or 	dx, dx
  2390 00005129 750D                <1> 	jnz 	short alloc_3 ; 1f
  2391                              <1> 		; bne 1f / branch if any free blocks in this word	
  2392 0000512B 6683C010            <1> 	add 	ax, 16
  2393                              <1> 		; add $16.,r1
  2394                              <1> 	; 09/01/2022
  2395 0000512F 39C8                <1> 	cmp	eax, ecx
  2396                              <1> 	;cmp 	ax, cx    
  2397                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2398 00005131 72EF                <1> 	jb 	short alloc_2
  2399                              <1> 		; blo 1b
  2400                              <1> 	; 14/11/2015
  2401                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2402                              <1> 	;	because of a (DMA or another) r/w error, 
  2403                              <1> 	;	we will be here, at 'jmp panic' code address,
  2404                              <1> 	;	even if the (disk) file system space is not full !!!
  2405                              <1> 	;	(cx = 0)	
  2406                              <1> 	;
  2407 00005133 E950E2FFFF          <1> 	jmp     panic 
  2408                              <1> 		; jmp panic / found no free storage
  2409                              <1> alloc_3: ; 1
  2410                              <1> 	; 09/01/2022
  2411 00005138 D1EA                <1> 	shr	edx, 1
  2412                              <1> 	;shr	dx, 1
  2413                              <1> 		; asr r3 / find a free block
  2414 0000513A 7203                <1> 	jc	short alloc_4 ; 1f
  2415                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2416                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2417                              <1> 	; 09/01/2022
  2418 0000513C 40                  <1> 	inc	eax
  2419                              <1> 	;inc	ax
  2420                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2421 0000513D EBF9                <1> 	jmp 	short alloc_3
  2422                              <1> 		; br 1b
  2423                              <1> alloc_4: ; 1:
  2424                              <1> 	;; pop cx ;; 01/08/2013
  2425                              <1> 		; tst (sp)+ / bump sp
  2426                              <1> 	; 02/04/2013 
  2427 0000513F E829000000          <1> 	call	free3
  2428                              <1> 		; jsr r0,3f / have found a free block
  2429                              <1> 	; 21/8/2012
  2430 00005144 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2431 00005147 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2432                              <1> 		; bic r3,(r2) / set bit for this block 
  2433                              <1> 		            ; / i.e. assign block
  2434                              <1> 		; br 2f
  2435 0000514A EB09                <1> 	jmp 	short alloc_5
  2436                              <1> 
  2437                              <1> free:
  2438                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2439                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2440                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2441                              <1> 	;
  2442                              <1> 	; calculates byte address and bit position for given block number
  2443                              <1> 	; then sets the corresponding bit in the free storage map
  2444                              <1> 	; 
  2445                              <1> 	; INPUTS ->
  2446                              <1> 	;    r1 - block number for a block structured device
  2447                              <1> 	;    cdev - current device 
  2448                              <1> 	; OUTPUTS ->
  2449                              <1> 	;    free storage map is updated
  2450                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2451                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2452                              <1> 	;
  2453                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2454                              <1>         ;  ((Modified registers: DX, CX))  
  2455                              <1> 
  2456                              <1> 		;mov r2,-(sp) / save r2, r3
  2457                              <1> 		;mov r3,-(sp)
  2458                              <1> 	;push 	ecx
  2459 0000514C 53                  <1> 	push 	ebx ; R2
  2460                              <1> 	;push 	edx ; R3 
  2461                              <1> 
  2462 0000514D E81B000000          <1>         call    free3
  2463                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2464                              <1> 				 ; / in free storage map for block
  2465 00005152 660913              <1> 	or 	[ebx], dx  
  2466                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2467                              <1> 			    ;  / indicates free block	
  2468                              <1> 	; 0 -> allocated, 1 -> free
  2469                              <1> 
  2470                              <1> alloc_5:
  2471                              <1> 	; 07/04/2013
  2472                              <1> free_1: ; 2:
  2473                              <1> 	;pop 	edx
  2474                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2475 00005155 5B                  <1> 	pop	ebx
  2476                              <1> 		; mov (sp)+,r2
  2477                              <1> 	; pop	ecx
  2478 00005156 803D[9F6E0000]00    <1> 	cmp 	byte [cdev], 0
  2479                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2480                              <1> 			 ; / cdev = 1, mountable device
  2481 0000515D 7707                <1> 	ja	short alloc_6 ; 1f
  2482                              <1> 		; bne 1f
  2483                              <1> 	;mov	byte [smod], 1
  2484 0000515F FE05[AD6E0000]      <1> 	inc 	byte [smod]
  2485                              <1> 		; incb smod / set super block modified for drum
  2486                              <1> 	; eAX (r1) = block number
  2487 00005165 C3                  <1> 	retn
  2488                              <1> 		; rts r0
  2489                              <1> free_2:
  2490                              <1> alloc_6: ; 1:
  2491                              <1> 	;mov 	byte [mmod], 1
  2492 00005166 FE05[AE6E0000]      <1> 	inc 	byte [mmod]
  2493                              <1> 		; incb	mmod 
  2494                              <1> 		  ; / set super block modified for mountable device
  2495                              <1> 	; eAX (r1) = block number
  2496 0000516C C3                  <1> 	retn	
  2497                              <1> 		; rts r0
  2498                              <1> free3:
  2499                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2500                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2501                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2502                              <1> 	;
  2503                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2504                              <1> 	; 
  2505                              <1> alloc_free_3: ; 3
  2506                              <1> 	;mov 	dx, 1
  2507                              <1> 	; 09/01/2022
  2508 0000516D 31D2                <1> 	xor	edx, edx
  2509 0000516F 42                  <1> 	inc	edx
  2510                              <1> 	; edx = 1
  2511 00005170 88C1                <1> 	mov 	cl, al
  2512                              <1> 		; mov r1,r2 / block number, k, = 1		
  2513 00005172 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2514                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2515 00005175 7402                <1> 	jz 	short free4
  2516                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2517                              <1> 			       ; / (k) mod 8
  2518                              <1> 	;shl 	dx, cl
  2519                              <1> 	; 09/01/2022
  2520 00005177 D3E2                <1> 	shl	edx, cl
  2521                              <1> free4:
  2522 00005179 0FB7D8              <1> 	movzx 	ebx, ax
  2523                              <1> 		; mov r1,r2 / divide block number by 16
  2524                              <1> 	; 09/01/2022
  2525 0000517C C1EB04              <1> 	shr	ebx, 4
  2526                              <1> 	;shr 	bx, 4
  2527                              <1> 		; asr r2
  2528                              <1> 		; asr r2
  2529                              <1> 		; asr r2
  2530                              <1> 		; asr r2
  2531                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2532                              <1> 		       ; / bit for block is in lower half of word
  2533                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2534                              <1> 		        ; / storage map
  2535                              <1> alloc_free_4: ; 1
  2536                              <1> 	; 09/01/2022
  2537 0000517F D1E3                <1> 	shl	ebx, 1
  2538                              <1> 	;shl 	bx, 1
  2539                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2540 00005181 81C3[7A7B0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2541                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2542                              <1> 	    		        ; / with block bit in it 	
  2543 00005187 803D[9F6E0000]00    <1> 	cmp	byte [cdev], 0
  2544                              <1> 		; tst cdev
  2545 0000518E 7606                <1> 	jna	short alloc_free_5
  2546                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2547 00005190 81C308020000        <1> 	add	ebx, mount - systm
  2548                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2549                              <1> 				    ; / mountable device with bit of block to be
  2550                              <1> 				    ; / freed
  2551                              <1> alloc_free_5: ; 1 
  2552 00005196 C3                  <1> 	retn
  2553                              <1> 		; rts r0 / return to 'free'
  2554                              <1> 	      ; 2
  2555                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2556                              <1> 	
  2557                              <1> iget:
  2558                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2559                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2560                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2561                              <1> 	;
  2562                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2563                              <1> 	;
  2564                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2565                              <1> 	; 
  2566                              <1> 	; INPUTS ->
  2567                              <1> 	;    ii - current i-number, rootdir
  2568                              <1> 	;    cdev - new i-node device
  2569                              <1> 	;    idev - current i-node device
  2570                              <1> 	;    imod - current i-node modified flag
  2571                              <1> 	;    mnti - cross device file i-number
  2572                              <1> 	;    r1 - i-numbe rof new i-node
  2573                              <1> 	;    mntd - mountable device number		
  2574                              <1> 	; 	 
  2575                              <1> 	; OUTPUTS ->
  2576                              <1> 	;    cdev, idev, imod, ii, r1
  2577                              <1> 	;
  2578                              <1> 	; ((AX = R1)) input/output
  2579                              <1> 	;
  2580                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2581                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2582                              <1> 
  2583 00005197 8A15[9F6E0000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2584 0000519D 8A35[9E6E0000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2585                              <1> 	;
  2586 000051A3 663B05[9C6E0000]    <1> 	cmp 	ax, [ii]
  2587                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2588 000051AA 7504                <1> 	jne 	short iget_1
  2589                              <1> 		; bne 1f
  2590 000051AC 38F2                <1> 	cmp	dl, dh
  2591                              <1> 		; cmp idev,cdev
  2592                              <1> 			  ; / is device number of i-node = current device
  2593 000051AE 7472                <1>         je      short iget_5
  2594                              <1> 		; beq 2f
  2595                              <1> iget_1: ; 1:
  2596 000051B0 30DB                <1> 	xor	bl, bl
  2597 000051B2 381D[AC6E0000]      <1> 	cmp	[imod], bl ; 0	
  2598                              <1> 		; tstb imod / has i-node of current file
  2599                              <1> 			  ; / been modified i.e., imod set
  2600 000051B8 7629                <1> 	jna	short iget_2
  2601                              <1> 		; beq 1f
  2602 000051BA 881D[AC6E0000]      <1> 	mov	[imod], bl ; 0
  2603                              <1> 		;  clrb	imod / if it has, 
  2604                              <1> 			   ; / we must write the new i-node out on disk
  2605                              <1> 	; 24/12/2021
  2606 000051C0 50                  <1> 	push	eax ; *
  2607                              <1> 	;push	ax
  2608                              <1> 		; mov r1,-(sp)
  2609                              <1> 	;mov	dl, [cdev]
  2610 000051C1 52                  <1> 	push	edx ; **
  2611                              <1> 	;push	dx
  2612                              <1> 		; mov cdev,-(sp)
  2613 000051C2 66A1[9C6E0000]      <1> 	mov	ax, [ii]
  2614                              <1> 		; mov ii,r1
  2615                              <1> 	;mov	dh, [idev]
  2616 000051C8 8835[9F6E0000]      <1> 	mov	[cdev], dh
  2617                              <1> 		; mov idev,cdev
  2618 000051CE FEC3                <1> 	inc	bl ; 1
  2619                              <1> 	; 31/07/2013
  2620 000051D0 881D[3C6F0000]      <1> 	mov     [rw], bl ; 1 == write 
  2621                              <1> 	;;28/07/2013 rw -> u.rw
  2622                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2623 000051D6 E848000000          <1> 	call	icalc
  2624                              <1> 		; jsr r0,icalc; 1
  2625                              <1> 	;pop	dx
  2626                              <1> 	; 24/12/2021
  2627 000051DB 5A                  <1> 	pop	edx ; **
  2628 000051DC 8815[9F6E0000]      <1> 	mov	[cdev], dl
  2629                              <1> 		; mov (sp)+,cdev
  2630                              <1> 	; 24/12/2021
  2631 000051E2 58                  <1> 	pop	eax ; *
  2632                              <1> 	;pop	ax
  2633                              <1> 		; mov (sp)+,r1
  2634                              <1> iget_2: ; 1:
  2635 000051E3 6621C0              <1> 	and	ax, ax
  2636                              <1> 		; tst r1 / is new i-number non zero
  2637 000051E6 7434                <1> 	jz	short iget_4 ; 2f
  2638                              <1> 		; beq 2f / branch if r1=0
  2639                              <1> 
  2640                              <1> 	;mov 	dl, [cdev]
  2641 000051E8 08D2                <1> 	or	dl, dl
  2642                              <1> 		; tst cdev / is the current device number non zero
  2643                              <1> 			 ; / (i.e., device =/ drum)
  2644 000051EA 7517                <1> 	jnz	short iget_3 ;  1f
  2645                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2646 000051EC 663B05[A46E0000]    <1> 	cmp	ax, [mnti]			
  2647                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2648                              <1> 			    ; / file (root directory of mounted device)
  2649 000051F3 750E                <1> 	jne	short iget_3 ; 1f
  2650                              <1> 		; bne 1f
  2651                              <1>         ;mov    bl, [mntd]
  2652 000051F5 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2653 000051F7 8815[9F6E0000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2654                              <1> 		; mov mntd,cdev / make mounted device the current device
  2655 000051FD 66A1[A86E0000]      <1> 	mov	ax, [rootdir]
  2656                              <1> 		; mov rootdir,r1
  2657                              <1> iget_3: ; 1:
  2658 00005203 66A3[9C6E0000]      <1> 	mov	[ii], ax
  2659                              <1> 		; mov r1,ii
  2660 00005209 8815[9E6E0000]      <1> 	mov	[idev], dl ; cdev
  2661                              <1> 		; mov cdev,idev
  2662 0000520F 30DB                <1> 	xor	bl, bl
  2663                              <1>         ; 31/07/2013
  2664 00005211 881D[3C6F0000]      <1> 	mov     [rw], bl ; 0 == read 
  2665                              <1> 	;;28/07/2013 rw -> u.rw       
  2666                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2667 00005217 E807000000          <1> 	call	icalc
  2668                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2669                              <1> iget_4: ; 2:
  2670 0000521C 66A1[9C6E0000]      <1> 	mov	ax, [ii]
  2671                              <1> 		; mov ii,r1
  2672                              <1> iget_5:
  2673 00005222 C3                  <1> 	retn
  2674                              <1> 		; rts r0
  2675                              <1> 
  2676                              <1> icalc:
  2677                              <1> 	; 09/01/2022
  2678                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2679                              <1> 	; 02/07/2015
  2680                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2681                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2682                              <1> 	;
  2683                              <1> 	; calculate physical block number from i-number then
  2684                              <1> 	; read or write that block
  2685                              <1> 	;
  2686                              <1> 	; 'icalc' is called from 'iget'
  2687                              <1> 	;
  2688                              <1> 	; for original unix v1:
  2689                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2690                              <1>        	; / (i+31.) mod 16. bytes from its start
  2691                              <1> 	;
  2692                              <1> 	; for retro unix 8086 v1:
  2693                              <1> 	;  i-node is located in block (i+47)/16 and
  2694                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2695                              <1> 	;
  2696                              <1> 	; INPUTS ->
  2697                              <1> 	;    r1 - i-number of i-node
  2698                              <1> 	; 	 
  2699                              <1> 	; OUTPUTS ->
  2700                              <1> 	;    inode r/w
  2701                              <1> 	;
  2702                              <1> 	; ((AX = R1)) input
  2703                              <1> 	;
  2704                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2705                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2706                              <1> 	;
  2707 00005223 0FB7D0              <1> 	movzx	edx, ax	
  2708 00005226 6683C22F            <1> 	add	dx, 47
  2709 0000522A 89D0                <1> 	mov	eax, edx
  2710                              <1> 	;add	ax, 47	; add 47 to inode number
  2711                              <1> 		; add $31.,r1 / add 31. to i-number
  2712 0000522C 50                  <1> 	push	eax
  2713                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2714                              <1> 	; 09/01/2022
  2715 0000522D C1E804              <1> 	shr	eax, 4
  2716                              <1> 	;shr 	ax, 4
  2717                              <1> 		; asr r1 / divide by 16.
  2718                              <1> 		; asr r1
  2719                              <1> 		; asr r1
  2720                              <1> 		; asr r1 / r1 contains block number of block
  2721                              <1> 		       ; / in which i-node exists
  2722 00005230 E8420A0000          <1> 	call	dskrd
  2723                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2724                              <1> 	; 31/07/2013
  2725 00005235 803D[3C6F0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2726                              <1> 	;; 28/07/2013 rw -> u.rw
  2727                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2728                              <1> 		; tst (r0)
  2729 0000523C 7605                <1> 	jna	short icalc_1
  2730                              <1> 		; beq 1f / branch to wslot when argument
  2731                              <1> 		       ; / in icalc call = 1
  2732                              <1> 	; eAX = r1 = block number
  2733 0000523E E8A60A0000          <1> 	call	wslot
  2734                              <1> 		; jsr r0,wslot / set up data buffer for write
  2735                              <1> 			     ; / (will be same buffer as dskrd got)
  2736                              <1> 	; eBX = r5 points to first word in data area for this block
  2737                              <1> icalc_1: ; 1:
  2738 00005243 5A                  <1> 	pop	edx 
  2739 00005244 83E20F              <1> 	and 	edx, 0Fh ; (i+47) mod 16
  2740                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2741                              <1> 			      ; / gives (i+31.) mod 16
  2742 00005247 C1E205              <1> 	shl 	edx, 5
  2743                              <1> 	; eDX = 32 * ((i+47) mod 16)
  2744 0000524A 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2745 0000524C 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2746                              <1>           	; eSI (r5) points to first word in i-node i.	
  2747                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2748                              <1> 			     ; / 32.*(i+31.)mod16
  2749                              <1> 		; mov $5,lsh / for i-node i.
  2750                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2751 0000524E BF[B86B0000]        <1> 	mov	edi, inode
  2752                              <1> 		; mov $inode,r1 / inode is address of first word 
  2753                              <1> 			      ; / of current i-node
  2754                              <1> 	; 09/01/2022
  2755 00005253 29C9                <1> 	sub	ecx, ecx
  2756 00005255 B108                <1> 	mov	cl, 8 
  2757                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2758                              <1> 		; mov $16.,r3
  2759                              <1>        ; 31/07/2013
  2760 00005257 382D[3C6F0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2761                              <1>        ;;28/07/2013 rw -> u.rw                 
  2762                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2763                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2764 0000525D 7609                <1> 	jna	short icalc_3
  2765                              <1> 		; beq 2f / r0 now contains proper return address 
  2766                              <1> 		       ; / for rts r0
  2767                              <1> icalc_2: ; 1:
  2768 0000525F 87F7                <1> 	xchg 	esi, edi
  2769                              <1> 	; overwrite old i-node (in buffer to be written)
  2770 00005261 F3A5                <1> 	rep 	movsd
  2771                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2772                              <1> 		; dec r3
  2773                              <1> 		; bgt 1b
  2774                              <1> 	;call	dskwr
  2775                              <1> 		; jsr r0,dskwr / write inode out on device
  2776                              <1> 	;retn
  2777                              <1> 		; rts r0
  2778                              <1> 	; 24/12/2021
  2779 00005263 E99D0A0000          <1> 	jmp	dskwr
  2780                              <1> 
  2781                              <1> icalc_3: ; 2:
  2782                              <1> 	; copy new i-node into inode area of (core) memory
  2783 00005268 F3A5                <1> 	rep 	movsd
  2784                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2785                              <1> 		                ; / "inode" area of core
  2786                              <1> 		; dec r3
  2787                              <1> 		; bgt 2b
  2788 0000526A C3                  <1> 	retn
  2789                              <1> 		; rts r0
  2790                              <1> 
  2791                              <1> access:
  2792                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2793                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2794                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2795                              <1> 	;
  2796                              <1> 	; check whether user is owner of file or user has read or write
  2797                              <1> 	; permission (based on i.flgs).
  2798                              <1> 	;
  2799                              <1> 	; INPUTS ->
  2800                              <1> 	;    r1 - i-number of file
  2801                              <1> 	;    u.uid
  2802                              <1> 	; arg0 -> (owner flag mask)	 		
  2803                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2804                              <1> 	; OUTPUTS ->
  2805                              <1> 	;    inode (or jump to error)
  2806                              <1> 	;
  2807                              <1> 	; ((AX = R1)) input/output
  2808                              <1> 	;
  2809                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2810                              <1> 	
  2811                              <1> 	;push	dx  ; save flags (DL)
  2812                              <1> 	; 24/12/2021
  2813 0000526B 52                  <1> 	push	edx ; save flags (DL)
  2814 0000526C E826FFFFFF          <1> 	call	iget
  2815                              <1> 		; jsr r0,iget / read in i-node for current directory
  2816                              <1> 			    ; / (i-number passed in r1)
  2817 00005271 8A0D[B86B0000]      <1> 	mov	cl, [i.flgs]
  2818                              <1> 		; mov i.flgs,r2
  2819                              <1> 	; 24/12/2021
  2820 00005277 5A                  <1> 	pop	edx ; restore flags (DL)
  2821                              <1> 	;pop	dx  ; restore flags (DL)
  2822 00005278 8A35[046F0000]      <1> 	mov	dh, [u.uid]
  2823 0000527E 3A35[BB6B0000]      <1> 	cmp	dh, [i.uid]
  2824                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2825 00005284 7503                <1> 	jne	short access_1
  2826                              <1> 		; bne 1f / no, then branch
  2827 00005286 C0E902              <1> 	shr	cl, 2
  2828                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2829                              <1> 		        ; / read/write bits
  2830                              <1> 		; asrb r2
  2831                              <1> access_1: ; 1:
  2832 00005289 20D1                <1> 	and	cl, dl
  2833                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2834                              <1> 			     ; / in access call
  2835 0000528B 7513                <1> 	jnz	short access_2
  2836                              <1> 		; bne 1f
  2837 0000528D 08F6                <1> 	or	dh, dh	; super user (root) ?
  2838                              <1> 		; tstb u.uid
  2839 0000528F 740F                <1> 	jz	short access_2 ; yes, super user
  2840                              <1> 	;jnz	error
  2841                              <1> 		; beq 1f
  2842                              <1> 		; jmp error
  2843 00005291 C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2843 00005299 0000                <1>
  2844                              <1> 			; 'permission denied !' error
  2845 0000529B E934E8FFFF          <1> 	jmp	error
  2846                              <1> 
  2847                              <1> access_2: ; 1:
  2848                              <1> 	; DL = flags
  2849 000052A0 C3                  <1> 	retn
  2850                              <1> 		; rts r0
  2851                              <1> 
  2852                              <1> setimod:
  2853                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2854                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2855                              <1> 	;
  2856                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2857                              <1> 	; the inode has been modified. Also puts the time of modification
  2858                              <1> 	; into the inode.
  2859                              <1> 	;
  2860                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2861                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2862                              <1> 	;
  2863                              <1> 	
  2864                              <1> 	;push 	edx
  2865 000052A1 50                  <1> 	push	eax
  2866                              <1> 
  2867 000052A2 C605[AC6E0000]01    <1> 	mov 	byte [imod], 1
  2868                              <1> 		; movb $1,imod / set current i-node modified bytes
  2869                              <1> 	; Erdogan Tan 14-7-2012
  2870 000052A9 E869E3FFFF          <1> 	call 	epoch
  2871                              <1> 		 ; mov s.time,i.mtim 
  2872                              <1> 			    ; / put present time into file modified time
  2873                              <1> 		 ; mov s.time+2,i.mtim+2
  2874                              <1> 
  2875 000052AE A3[D26B0000]        <1> 	mov 	[i.mtim], eax
  2876                              <1> 	
  2877                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2878                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2879 000052B3 833D[CE6B0000]00    <1> 	cmp	dword [i.ctim], 0
  2880 000052BA 7505                <1> 	jnz	short setimod_ok
  2881                              <1> 
  2882 000052BC A3[CE6B0000]        <1> 	mov 	[i.ctim], eax
  2883                              <1> 
  2884                              <1> setimod_ok: ; 31/07/2013
  2885 000052C1 58                  <1> 	pop	eax
  2886                              <1> 	;pop	edx
  2887                              <1> 	
  2888 000052C2 C3                  <1> 	retn
  2889                              <1> 		; rts r0
  2890                              <1> 
  2891                              <1> itrunc:
  2892                              <1> 	; 03/02/2022
  2893                              <1> 	; 09/01/2022
  2894                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2895                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2896                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2897                              <1> 	;
  2898                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2899                              <1> 	;  to zero length.
  2900                              <1> 	;
  2901                              <1> 	; INPUTS ->
  2902                              <1> 	;    r1 - i-number of i-node
  2903                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2904                              <1> 	;    i.flgs - large file flag		
  2905                              <1> 	;    i.size - size of file	
  2906                              <1> 	; 	 
  2907                              <1> 	; OUTPUTS ->
  2908                              <1> 	;    i.flgs - large file flag is cleared
  2909                              <1> 	;    i.size - set to 0	
  2910                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2911                              <1> 	;    setimod - set to indicate i-node has been modified
  2912                              <1> 	;    r1 - i-number of i-node  					
  2913                              <1> 	;
  2914                              <1> 	; ((AX = R1)) input/output
  2915                              <1> 	;
  2916                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2917                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2918                              <1> 
  2919 000052C3 E8CFFEFFFF          <1> 	call	iget
  2920                              <1> 		; jsr r0,iget
  2921 000052C8 BE[BE6B0000]        <1> 	mov	esi, i.dskp
  2922                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2923 000052CD 31C0                <1> 	xor	eax, eax
  2924                              <1> itrunc_1: ; 1:
  2925 000052CF 66AD                <1> 	lodsw
  2926                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2927                              <1> 	; 09/01/2022
  2928 000052D1 09C0                <1> 	or	eax, eax
  2929                              <1> 	;or 	ax, ax
  2930 000052D3 7433                <1> 	jz	short itrunc_5
  2931                              <1> 		; beq 5f
  2932 000052D5 56                  <1> 	push	esi
  2933                              <1> 		; mov r2,-(sp)
  2934                              <1> 	; 09/01/2022
  2935 000052D6 F605[B96B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2936                              <1> 	;test	word [i.flgs], 1000h
  2937                              <1> 		; bit $10000,i.flgs / test large file bit?
  2938 000052DD 7423                <1> 	jz	short itrunc_4
  2939                              <1> 		; beq 4f / if clear, branch
  2940 000052DF 50                  <1> 	push	eax
  2941                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2942 000052E0 E892090000          <1> 	call	dskrd
  2943                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2944                              <1> 			     ; / pointed to by r5
  2945                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2946                              <1> 	; 09/01/2022
  2947 000052E5 31C9                <1> 	xor	ecx, ecx
  2948 000052E7 FEC5                <1> 	inc	ch ; mov ch, 1
  2949                              <1> 	; ecx = 256
  2950                              <1> 	;mov	ecx, 256
  2951                              <1> 		; mov $256.,r3 / move word count into r3
  2952 000052E9 89DE                <1> 	mov	esi, ebx
  2953                              <1> itrunc_2: ; 2:
  2954 000052EB 66AD                <1> 	lodsw
  2955                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2956                              <1> 			     ; / physical block number
  2957                              <1> 	; 09/01/2022
  2958 000052ED 21C0                <1> 	and	eax, eax
  2959                              <1> 	;and	ax, ax
  2960 000052EF 7407                <1> 	jz	short itrunc_3
  2961                              <1> 		; beq 3f / branch if zero
  2962                              <1> 	; 24/12/2021
  2963 000052F1 51                  <1> 	push	ecx
  2964                              <1> 	;push	cx
  2965                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2966                              <1> 	;push	esi
  2967                              <1> 		; mov r5,-(sp)
  2968 000052F2 E855FEFFFF          <1> 	call	free
  2969                              <1> 		; jsr r0,free / free block in free storage map
  2970                              <1> 	;pop	esi
  2971                              <1> 		; mov(sp)+,r5
  2972                              <1> 	;pop	cx
  2973 000052F7 59                  <1> 	pop	ecx
  2974                              <1> 		; mov (sp)+,r3
  2975                              <1> itrunc_3: ; 3:
  2976 000052F8 E2F1                <1> 	loop	itrunc_2
  2977                              <1> 		; dec r3 / decrement word count
  2978                              <1> 		; bgt 2b / branch if positive
  2979 000052FA 58                  <1> 	pop	eax
  2980                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2981                              <1> 			     ; / indirect block
  2982                              <1> 	; 01/08/2013
  2983                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2984                              <1> 	; 03/02/2022
  2985 000052FB 8025[B96B0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2986                              <1> itrunc_4: ; 4:
  2987 00005302 E845FEFFFF          <1> 	call	free
  2988                              <1> 		; jsr r0,free / free indirect block
  2989 00005307 5E                  <1> 	pop	esi
  2990                              <1> 		; mov (sp)+,r2
  2991                              <1> itrunc_5: ; 5:
  2992 00005308 81FE[CE6B0000]      <1> 	cmp	esi, i.dskp+16
  2993                              <1> 		; cmp r2,$i.dskp+16.
  2994 0000530E 72BF                <1> 	jb	short itrunc_1	
  2995                              <1> 		; bne 1b / branch until all i.dskp entries check
  2996                              <1> 	; 03/02/2022
  2997                              <1> 	;and	byte [i.flgs+1], 0EFh
  2998                              <1> 	; 01/08/2013
  2999                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3000                              <1> 		; bic $10000,i.flgs / clear large file bit
  3001 00005310 BF[BE6B0000]        <1> 	mov	edi, i.dskp
  3002                              <1> 	;mov	cx, 8
  3003                              <1> 	;xor 	ax, ax
  3004                              <1> 	; 09/01/2022
  3005 00005315 29C9                <1> 	sub	ecx, ecx
  3006 00005317 B108                <1> 	mov	cl, 8
  3007 00005319 29C0                <1> 	sub	eax, eax
  3008 0000531B 66A3[BC6B0000]      <1> 	mov	[i.size], ax ; 0
  3009                              <1> 		; clr i.size / zero file size
  3010 00005321 F366AB              <1> 	rep	stosw
  3011                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3012                              <1> 			   ; / zero block pointers
  3013 00005324 E878FFFFFF          <1> 	call	setimod
  3014                              <1> 		; jsr r0,setimod / set i-node modified flag
  3015 00005329 66A1[9C6E0000]      <1> 	mov	ax, [ii]
  3016                              <1> 		; mov ii,r1
  3017 0000532F C3                  <1> 	retn
  3018                              <1> 		; rts r0
  3019                              <1> 
  3020                              <1> imap:
  3021                              <1> 	; 11/02/2022
  3022                              <1> 	; 03/02/2022
  3023                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3024                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3025                              <1> 	;
  3026                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3027                              <1> 	; allocation bit for an i-node whose number in r1.
  3028                              <1> 	;
  3029                              <1> 	; INPUTS ->
  3030                              <1> 	;    r1 - contains an i-number
  3031                              <1> 	;    fsp - start of table containing open files
  3032                              <1> 	;
  3033                              <1> 	; OUTPUTS ->
  3034                              <1> 	;    r2 - byte address of byte with the allocation bit
  3035                              <1> 	;    mq - a mask to locate the bit position.	
  3036                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3037                              <1> 	;
  3038                              <1> 	; ((AX = R1)) input/output
  3039                              <1> 	; ((DL/DX = MQ)) output
  3040                              <1> 	; ((BX = R2)) output
  3041                              <1> 	;
  3042                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3043                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3044                              <1> 	;
  3045                              <1> 		; / get the byte that has the allocation bit for 
  3046                              <1> 		; / the i-number contained in r1
  3047                              <1> 	;mov	dx, 1
  3048 00005330 B201                <1> 	mov	dl, 1
  3049                              <1> 		; mov $1,mq / put 1 in the mq
  3050 00005332 0FB7D8              <1> 	movzx	ebx, ax
  3051                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3052                              <1>  		          ; / in the map we must find
  3053 00005335 6683EB29            <1> 	sub	bx, 41
  3054                              <1> 		; sub $41.,r2 / r2 has i-41
  3055 00005339 88D9                <1> 	mov	cl, bl
  3056                              <1> 		; mov r2,r3 / r3 has i-41
  3057 0000533B 80E107              <1> 	and	cl, 7
  3058                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3059                              <1> 			   ; / the bit position
  3060 0000533E 7402                <1> 	jz	short imap1
  3061                              <1> 	;shl	dx, cl
  3062 00005340 D2E2                <1> 	shl	dl, cl
  3063                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3064                              <1> imap1:			   ; / to the left to mask the correct bit
  3065                              <1> 	; 03/02/2022
  3066 00005342 C1EB03              <1> 	shr	ebx, 3
  3067                              <1> 	;shr	bx, 3
  3068                              <1> 		; asr r2
  3069                              <1> 		; asr r2
  3070                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3071                              <1> 		       ; / from the start of the map
  3072                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3073 00005345 BE[787B0000]        <1> 	mov	esi, systm
  3074                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3075                              <1> 				; / the super block for drum
  3076                              <1> 	;cmp	word [cdev], 0
  3077 0000534A 803D[9F6E0000]00    <1> 	cmp	byte [cdev], 0
  3078                              <1> 		; tst cdev / is the device the disk
  3079 00005351 7606                <1> 	jna	short imap2
  3080                              <1> 		; beq 1f / yes
  3081 00005353 81C608020000        <1> 	add	esi, mount - systm
  3082                              <1> 		; add $mount-systm,r2 / for mounted device,
  3083                              <1> 			; / r2 points to 1st word of its super block
  3084                              <1> imap2: ; 1:
  3085 00005359 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3086                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3087 0000535C 6683C304            <1> 	add	bx, 4
  3088 00005360 01F3                <1> 	add	ebx, esi
  3089                              <1>         	; add (sp)+,r2 / ?
  3090                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3091                              <1> 		      ;; (2 + free map size + 2)
  3092                              <1> 		; add $2,r2 / ?
  3093                              <1> 
  3094                              <1> 	; 11/02/2022
  3095 00005362 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3096 00005368 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3097                              <1> 			  ; if inode num overs inode count
  3098                              <1> 
  3099                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3100                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3101                              <1> 
  3102                              <1> 	; 11/02/2022
  3103                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3104                              <1> 	;	(number of requested inode > inode count)
  3105                              <1> 
  3106 0000536A C3                  <1> 	retn
  3107                              <1> 		; rts r0
  2093                                  %include 'u6.s'        ; 31/05/2015
  2094                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS6.INC
  2095                              <1> ; Last Modification: 03/02/2022
  2096                              <1> ; ----------------------------------------------------------------------------
  2097                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2098                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2099                              <1> ;
  2100                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2101                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2102                              <1> ; <Bell Laboratories (17/3/1972)>
  2103                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2104                              <1> ;
  2105                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2106                              <1> ;
  2107                              <1> ; ****************************************************************************
  2108                              <1> 
  2109                              <1> readi:
  2110                              <1> 	; 11/01/2022
  2111                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2112                              <1> 	; 20/05/2015
  2113                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2114                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2115                              <1> 	;
  2116                              <1> 	; Reads from an inode whose number in R1
  2117                              <1> 	; 
  2118                              <1> 	; INPUTS ->
  2119                              <1> 	;    r1 - inode number
  2120                              <1> 	;    u.count - byte count user desires
  2121                              <1> 	;    u.base - points to user buffer
  2122                              <1> 	;    u.fofp - points to word with current file offset
  2123                              <1> 	; OUTPUTS ->
  2124                              <1> 	;    u.count - cleared
  2125                              <1> 	;    u.nread - accumulates total bytes passed back
  2126                              <1> 	;
  2127                              <1> 	; ((AX = R1)) input/output
  2128                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2129                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2130                              <1> 
  2131 0000536B 31D2                <1> 	xor	edx, edx ; 0
  2132 0000536D 8915[E06E0000]      <1> 	mov 	[u.nread], edx ; 0
  2133                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2134 00005373 668915[1D6F0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2135 0000537A 3915[DC6E0000]      <1> 	cmp 	[u.count], edx ; 0
  2136                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2137 00005380 7701                <1> 	ja 	short readi_1 ; 1f
  2138                              <1> 		 ; bgt 1f / yes, branch
  2139 00005382 C3                  <1> 	retn
  2140                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2141                              <1> readi_1: ; 1:
  2142                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2143 00005383 6683F828            <1> 	cmp	ax, 40
  2144                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2145                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2146                              <1>         ;ja	dskr 
  2147                              <1> 		 ; ble 1f / yes, branch
  2148                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2149                              <1> 		 ;         / read file with i-node number (r1)
  2150                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2151                              <1> 	; 24/12/2021
  2152 00005387 7605                <1> 	jna	short readi_3
  2153 00005389 E9CF000000          <1> 	jmp	dskr
  2154                              <1> readi_3:
  2155                              <1> 	; (20/05/2015)
  2156 0000538E 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2157                              <1> 	; 1:
  2158 0000538F 0FB6D8              <1> 	movzx	ebx, al
  2159                              <1> 	; 11/01/2022
  2160 00005392 C1E302              <1> 	shl	ebx, 2
  2161                              <1> 	;shl	bx, 2
  2162                              <1> 		 ; asl r1 / multiply inode number by 2
  2163 00005395 81C3[99530000]      <1> 	add	ebx, readi_2 - 4
  2164 0000539B FF23                <1> 	jmp	dword [ebx]	
  2165                              <1> 		 ; jmp *1f-2(r1)
  2166                              <1> readi_2: ; 1:
  2167 0000539D [E9530000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2168                              <1> 		 ;rtty / tty; r1=2
  2169                              <1> 		 ;rppt / ppt; r1=4
  2170 000053A1 [39540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2171                              <1> 		 ;rmem / mem; r1=6
  2172                              <1> 		 ;rrf0 / rf0
  2173                              <1> 		 ;rrk0 / rk0
  2174                              <1> 		 ;rtap / tap0
  2175                              <1> 		 ;rtap / tap1
  2176                              <1> 		 ;rtap / tap2
  2177                              <1> 		 ;rtap / tap3
  2178                              <1> 		 ;rtap / tap4
  2179                              <1> 		 ;rtap / tap5
  2180                              <1> 		 ;rtap / tap6
  2181                              <1> 		 ;rtap / tap7
  2182 000053A5 [285B0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2183 000053A9 [285B0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2184 000053AD [285B0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2185 000053B1 [285B0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2186 000053B5 [285B0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2187 000053B9 [285B0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2188 000053BD [4E540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2189 000053C1 [35540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2190                              <1> 		 ;rcvt / tty0
  2191 000053C5 [35540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2192                              <1> 		 ;rcvt / tty1
  2193 000053C9 [35540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2194                              <1> 		 ;rcvt / tty2
  2195 000053CD [35540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2196                              <1> 		 ;rcvt / tty3
  2197 000053D1 [35540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2198                              <1> 		 ;rcvt / tty4
  2199 000053D5 [35540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2200                              <1> 		 ;rcvt / tty5
  2201 000053D9 [35540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2202                              <1> 		 ;rcvt / tty6
  2203 000053DD [35540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2204                              <1> 		 ;rcvt / tty7
  2205 000053E1 [35540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2206                              <1> 		 ;rcrd / crd
  2207 000053E5 [35540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2208                              <1> 
  2209                              <1> rtty: ; / read from console tty
  2210                              <1> 	; 11/01/2022
  2211                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2212                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2213                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2214                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2215                              <1> 	;	     must be written immediate on video page (screen)
  2216                              <1> 	;	     when it is required.	
  2217                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2218                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2219                              <1> 	;
  2220                              <1> 	; Console tty buffer is PC keyboard buffer
  2221                              <1> 	; and keyboard-keystroke handling is different than original
  2222                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2223                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2224                              <1> 	;
  2225                              <1> 	; 06/12/2013
  2226 000053E9 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2227 000053F0 8A83[176C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2228                              <1> rttys:
  2229                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2230                              <1> 	               ; / of the control and status block
  2231                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2232                              <1> 		       ; / tty buffer
  2233                              <1> 	; 28/07/2013
  2234 000053F6 A2[0C6F0000]        <1> 	mov 	[u.ttyn], al
  2235                              <1> 	; 13/01/2014
  2236 000053FB FEC0                <1> 	inc	al
  2237 000053FD A2[E86E0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2238                              <1> rtty_nc: ; 01/02/2014
  2239                              <1> 	; 29/09/2013
  2240                              <1> 	;mov	ecx, 10
  2241                              <1> 	; 11/01/2022
  2242 00005402 29C9                <1> 	sub	ecx, ecx
  2243 00005404 B10A                <1> 	mov	cl, 10
  2244                              <1> rtty_1: 	; 01/02/2014
  2245                              <1> 	;push 	cx ; 29/09/2013
  2246                              <1> 	; 24/12/2021
  2247 00005406 51                  <1> 	push	ecx
  2248                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2249 00005407 B001                <1> 	mov 	al, 1
  2250 00005409 E86A0B0000          <1> 	call 	getc
  2251                              <1> 	; 24/12/2021
  2252 0000540E 59                  <1> 	pop	ecx
  2253                              <1> 	;pop 	cx ; 29/09/2013	
  2254 0000540F 7516                <1> 	jnz	short rtty_2
  2255                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2256                              <1> 	               ; / of chars. Is this number non-zero?
  2257 00005411 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2258                              <1> 	; 05/10/2013
  2259 00005413 8A25[0C6F0000]      <1> 	mov	ah, [u.ttyn]
  2260                              <1> 	; 29/09/2013
  2261 00005419 E89AFBFFFF          <1> 	call	sleep
  2262                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2263                              <1>                 ;           / (120 chars.)
  2264                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2265 0000541E EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2266                              <1> 
  2267                              <1> rtty_idle:
  2268                              <1> 	; 29/07/2013
  2269 00005420 E806FBFFFF          <1> 	call 	idle
  2270 00005425 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2271                              <1> 	;1:
  2272                              <1> 		; tst 2(r5) / is the number of characters zero
  2273                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2274                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2275                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2276                              <1> 		          ; / contains the next char.
  2277                              <1> 		; dec 2(r5) / decrement the character count
  2278                              <1> rtty_2:
  2279 00005427 30C0                <1> 	xor 	al, al
  2280 00005429 E84A0B0000          <1> 	call 	getc
  2281 0000542E E892000000          <1> 	call	passc
  2282                              <1> 		; jsr r0,passc / move the character to core (user)
  2283                              <1> 	;; 17/10/2015 - 16/07/2015
  2284                              <1> 	; 19/06/2014
  2285                              <1> 	;;jnz	short rtty_nc
  2286 00005433 58                  <1> 	pop	eax  ; (20/05/2015)
  2287 00005434 C3                  <1> 	retn 
  2288                              <1> ;ret1:
  2289                              <1> 		; jmp ret / return to caller via 'ret'
  2290                              <1> 
  2291                              <1> rcvt:   ; < receive/read character from tty >
  2292                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2293                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2294                              <1> 	;
  2295                              <1> 	; Retro UNIX 8086 v1 modification !
  2296                              <1> 	; 
  2297                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2298                              <1> 	;		(exactly different than this one)
  2299                              <1> 	;	was in 'u9.s' file.
  2300                              <1> 	;
  2301 00005435 2C0A                <1> 	sub 	al, 10
  2302                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2303                              <1> 	; 16/07/2013
  2304                              <1> 	; 21/05/2013
  2305 00005437 EBBD                <1>         jmp     short rttys
  2306                              <1>       
  2307                              <1> ;rppt: / read paper tape
  2308                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2309                              <1> ;			 / places
  2310                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2311                              <1> ;		       / also enables read bit in prs
  2312                              <1> ;	jsr	r0,passc / place character in users buffer area
  2313                              <1> ;	br	rppt
  2314                              <1> 
  2315                              <1> rmem: ; / transfer characters from memory to a user area of core
  2316                              <1> 	; 17/10/2015
  2317                              <1> 	; 11/06/2015
  2318                              <1> 	; 24/05/2015
  2319                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2320                              <1> 	;
  2321 00005439 8B35[C86E0000]      <1> 	mov     esi, [u.fofp]
  2322                              <1> rmem_1:
  2323 0000543F 8B1E                <1>         mov     ebx, [esi]        
  2324                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2325                              <1> 		               ; / to be transferred to user
  2326 00005441 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2327                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2328                              <1> 			    ; / char in memory file
  2329 00005443 8A03                <1> 	mov	al, [ebx]
  2330                              <1> 		; movb (r1),r1 / get character from memory file, 
  2331                              <1> 		             ; / put it in r1
  2332 00005445 E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2333                              <1> 			     ;  / the next byte of the users core area
  2334                              <1> 		; br rmem / continue
  2335 0000544A 75F3                <1> 	jnz	short rmem_1
  2336                              <1> ret_:
  2337 0000544C 58                  <1> 	pop	eax ; 09/06/2015
  2338 0000544D C3                  <1> 	retn
  2339                              <1> 
  2340                              <1> rlpr:
  2341                              <1> ;1:
  2342                              <1> ;rcrd:
  2343 0000544E C705[0D6F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2343 00005456 0000                <1>
  2344 00005458 E977E6FFFF          <1> 	jmp	error
  2345                              <1> 		;jmp	error / see 'error' routine
  2346                              <1> 
  2347                              <1> dskr:
  2348                              <1> 	; 12/10/2015
  2349                              <1> 	; 21/08/2015
  2350                              <1> 	; 25/07/2015
  2351                              <1> 	; 10/07/2015
  2352                              <1> 	; 16/06/2015
  2353                              <1> 	; 31/05/2015
  2354                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2355                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2356                              <1> dskr_0:
  2357 0000545D 50                  <1> 	push	eax
  2358                              <1> 		; mov (sp),r1 / i-number in r1
  2359                              <1> 	; AX = i-number
  2360 0000545E E834FDFFFF          <1> 	call	iget
  2361                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2362 00005463 0FB715[BC6B0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2363                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2364 0000546A 8B1D[C86E0000]      <1> 	mov	ebx, [u.fofp]
  2365 00005470 2B13                <1> 	sub	edx, [ebx]
  2366                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2367                              <1>         ; 12/10/2015
  2368                              <1> 	; jna     short ret_ 
  2369                              <1> 		; blos ret
  2370 00005472 7709                <1> 	ja	short dskr_1
  2371                              <1> 	;
  2372                              <1> dskr_retn: ; 12/10/2015
  2373 00005474 58                  <1> 	pop	eax
  2374 00005475 C605[1F6F0000]00    <1> 	mov	byte [u.kcall], 0
  2375 0000547C C3                  <1> 	retn	
  2376                              <1> dskr_1: 
  2377 0000547D 3B15[DC6E0000]      <1> 	cmp     edx, [u.count] 
  2378                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2379                              <1> 			       ; / to carry out read
  2380 00005483 7306                <1> 	jnb	short dskr_2
  2381                              <1> 		; bhis 1f
  2382 00005485 8915[DC6E0000]      <1> 	mov	[u.count], edx
  2383                              <1> 		; mov r2,u.count / no, just read to end of file
  2384                              <1> dskr_2: ; 1:
  2385                              <1> 	; AX = i-number
  2386 0000548B E8A0FBFFFF          <1> 	call	mget
  2387                              <1> 		; jsr r0,mget / returns physical block number of block 
  2388                              <1> 			    ; / in file where offset points
  2389                              <1> 	; eAX = physical block number
  2390 00005490 E8E2070000          <1> 	call	dskrd
  2391                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2392                              <1> 			     ; / 1st word of data in buffer
  2393                              <1> 	; 09/06/2015
  2394 00005495 803D[1F6F0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2395 0000549C 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2396 0000549E 66833D[1D6F0000]00  <1> 	cmp	word [u.pcount], 0
  2397 000054A6 7705                <1> 	ja	short dskr_4
  2398                              <1> dskr_3:
  2399                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2400 000054A8 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2401                              <1> dskr_4:
  2402                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2403 000054AD E8BC020000          <1> 	call	sioreg
  2404                              <1> 		; jsr r0,sioreg
  2405 000054B2 87F7                <1> 	xchg	esi, edi
  2406                              <1> 	; eDI = file (user data) offset
  2407                              <1> 	; eSI = sector (I/O) buffer offset
  2408                              <1> 	; eCX = byte count
  2409 000054B4 F3A4                <1> 	rep	movsb
  2410                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2411                              <1> 		                 ; / starting at u.base
  2412                              <1> 		; dec r3
  2413                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2414                              <1> 	; 25/07/2015
  2415                              <1> 	; eax = remain bytes in buffer
  2416                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2417 000054B6 09C0                <1> 	or	eax, eax
  2418 000054B8 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2419                              <1> 	; 03/08/2013
  2420                              <1> 	;pop	eax
  2421 000054BA 390D[DC6E0000]      <1> 	cmp	[u.count], ecx ; 0
  2422                              <1> 		; tst u.count / all bytes read off disk
  2423                              <1> 		; bne dskr
  2424                              <1> 		; br ret
  2425                              <1>         ;ja	short dskr_0
  2426                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2427                              <1> 	;retn
  2428                              <1> 	; 12/10/2015
  2429 000054C0 76B2                <1> 	jna	short dskr_retn
  2430 000054C2 58                  <1> 	pop	eax  ; (i-node number)
  2431 000054C3 EB98                <1> 	jmp	short dskr_0
  2432                              <1> 	
  2433                              <1> passc:
  2434                              <1> 	; 18/10/2015
  2435                              <1> 	; 10/07/2015
  2436                              <1> 	; 01/07/2015
  2437                              <1> 	; 08/06/2015
  2438                              <1> 	; 04/06/2015
  2439                              <1> 	; 20/05/2015
  2440                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2441                              <1> 	;
  2442                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2443                              <1> 	;		      to physical address
  2444 000054C5 66833D[1D6F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2445                              <1> 			     ; 1-4095 --> use previous physical base address
  2446                              <1> 			     ; in [u.pbase]
  2447 000054CD 7705                <1> 	ja	short passc_3
  2448                              <1> 	; 08/06/2015 - 10/07/2015
  2449 000054CF E82C000000          <1> 	call	trans_addr_w
  2450                              <1> passc_3:
  2451                              <1> 	; 19/05/2015
  2452 000054D4 66FF0D[1D6F0000]    <1> 	dec	word [u.pcount]
  2453                              <1> 	;
  2454 000054DB 8B1D[196F0000]      <1> 	mov	ebx, [u.pbase]
  2455 000054E1 8803                <1> 	mov	[ebx], al
  2456                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2457                              <1> 		               ; / users buffer
  2458 000054E3 FF05[D86E0000]      <1> 	inc	dword [u.base]
  2459                              <1> 		; inc u.base / increment the pointer to point to 
  2460                              <1> 			  ; / the next byte in users buffer
  2461 000054E9 FF05[196F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2462 000054EF FF05[E06E0000]      <1> 	inc	dword [u.nread]
  2463                              <1> 		; inc u.nread / increment the number of bytes read
  2464 000054F5 FF0D[DC6E0000]      <1> 	dec	dword [u.count]
  2465                              <1> 		; dec u.count / decrement the number of bytes to be read
  2466                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2467 000054FB C3                  <1> 	retn
  2468                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2469                              <1> 		             ; / 'readi' by:
  2470                              <1> 		;/ (1) pop the return address off the stack into r0
  2471                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2472                              <1> 	;1:
  2473                              <1> 		; clr	*$ps / clear processor status
  2474                              <1> 		; rts r0 / return to address currently on top of stack
  2475                              <1> 
  2476                              <1> trans_addr_r:
  2477                              <1> 	; Translate virtual address to physical address 
  2478                              <1> 	; for reading from user's memory space
  2479                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2480                              <1> 	; 18/10/2015
  2481                              <1> 	; 10/07/2015
  2482                              <1> 	; 09/06/2015
  2483                              <1> 	; 08/06/2015 
  2484                              <1> 	; 04/06/2015
  2485                              <1> 	;
  2486                              <1> 	; 18/10/2015
  2487 000054FC 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2488 000054FE EB04                <1> 	jmp 	short trans_addr_rw
  2489                              <1> 
  2490                              <1> 	;push	eax
  2491                              <1> 	;push	ebx
  2492                              <1> 	;mov	ebx, [u.base]
  2493                              <1> 	;call	get_physical_addr ; get physical address
  2494                              <1> 	;;jnc	short cpass_0
  2495                              <1> 	;jnc	short passc_1
  2496                              <1> 	;mov	[u.error], eax
  2497                              <1> 	;;pop	ebx
  2498                              <1> 	;;pop	eax
  2499                              <1> 	;jmp	error
  2500                              <1> ;cpass_0:
  2501                              <1> 	; 18/10/2015
  2502                              <1> 	; 20/05/2015
  2503                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2504                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2505                              <1> 	;pop	ebx
  2506                              <1> 	;pop	eax
  2507                              <1> 	;retn	; 08/06/2015
  2508                              <1> 
  2509                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2510                              <1> trans_addr_w:
  2511                              <1> 	; 31/12/2021
  2512                              <1> 	; Translate virtual address to physical address 
  2513                              <1> 	; for writing to user's memory space
  2514                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2515                              <1> 	; 18/10/2015
  2516                              <1> 	; 29/07/2015
  2517                              <1> 	; 10/07/2015
  2518                              <1> 	; 09/06/2015
  2519                              <1> 	; 08/06/2015
  2520                              <1> 	; 04/06/2015 (passc)
  2521                              <1> 	;
  2522                              <1> 	; 18/10/2015
  2523 00005500 29D2                <1> 	sub	edx, edx
  2524 00005502 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2525                              <1> trans_addr_rw:
  2526 00005504 50                  <1> 	push	eax
  2527 00005505 53                  <1> 	push	ebx
  2528                              <1> 	; 18/10/2015
  2529 00005506 52                  <1> 	push 	edx ; r/w sign (in DL)
  2530                              <1> 	;
  2531 00005507 8B1D[D86E0000]      <1> 	mov	ebx, [u.base]
  2532 0000550D E892DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2533 00005512 730A                <1> 	jnc	short passc_0
  2534 00005514 A3[0D6F0000]        <1> 	mov	[u.error], eax
  2535                              <1> 	;pop	edx
  2536                              <1> 	;pop 	ebx
  2537                              <1> 	;pop	eax
  2538 00005519 E9B6E5FFFF          <1> 	jmp	error
  2539                              <1> passc_0:
  2540 0000551E F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2541 00005521 5A                  <1> 	pop	edx ; 18/10/2015
  2542 00005522 7517                <1> 	jnz	short passc_1
  2543                              <1> 	; 18/10/2015
  2544 00005524 20D2                <1> 	and 	dl, dl
  2545 00005526 7413                <1> 	jz	short passc_1
  2546                              <1> 	; 20/05/2015
  2547                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2548                              <1> 	; EBX = linear address
  2549 00005528 51                  <1> 	push 	ecx
  2550 00005529 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2551 0000552A E8E4DBFFFF          <1> 	call 	copy_page
  2552 0000552F 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2553 00005530 59                  <1> 	pop	ecx
  2554 00005531 7217                <1> 	jc	short passc_2
  2555                              <1> 	; 24/12/2021
  2556                              <1> 	;push	eax ; physical address of the new/allocated page
  2557                              <1> 	;call	add_to_swap_queue
  2558                              <1> 	;pop	eax
  2559                              <1> 	; 18/10/2015
  2560 00005533 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2561                              <1> 	;mov 	ecx, PAGE_SIZE
  2562                              <1> 	;sub	ecx, ebx 
  2563 00005539 01D8                <1> 	add	eax, ebx  
  2564                              <1> passc_1: 
  2565                              <1> 	; 18/10/2015
  2566                              <1> 	; 20/05/2015
  2567 0000553B A3[196F0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2568 00005540 66890D[1D6F0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2569 00005547 5B                  <1> 	pop	ebx
  2570 00005548 58                  <1> 	pop	eax
  2571 00005549 C3                  <1> 	retn	; 08/06/2015
  2572                              <1> passc_2:
  2573 0000554A C705[0D6F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2573 00005552 0000                <1>
  2574                              <1> 	;pop 	ebx
  2575                              <1> 	;pop	eax
  2576 00005554 E97BE5FFFF          <1> 	jmp	error
  2577                              <1> 
  2578                              <1> writei:
  2579                              <1> 	; 03/02/2022
  2580                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2581                              <1> 	; 20/05/2015
  2582                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2583                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2584                              <1> 	;
  2585                              <1> 	; Write data to file with inode number in R1
  2586                              <1> 	; 
  2587                              <1> 	; INPUTS ->
  2588                              <1> 	;    r1 - inode number
  2589                              <1> 	;    u.count - byte count to be written
  2590                              <1> 	;    u.base - points to user buffer
  2591                              <1> 	;    u.fofp - points to word with current file offset
  2592                              <1> 	; OUTPUTS ->
  2593                              <1> 	;    u.count - cleared
  2594                              <1> 	;    u.nread - accumulates total bytes passed back	
  2595                              <1> 	; ((AX = R1))
  2596                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2597                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2598                              <1> 
  2599 00005559 31C9                <1> 	xor	ecx, ecx
  2600 0000555B 890D[E06E0000]      <1> 	mov 	[u.nread], ecx  ; 0
  2601                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2602                              <1> 		            ; / read or write calls
  2603 00005561 66890D[1D6F0000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2604 00005568 390D[DC6E0000]      <1> 	cmp 	[u.count], ecx
  2605                              <1> 	;	; tst u.count / test the byte count specified by the user
  2606 0000556E 7701                <1> 	ja 	short writei_1 ; 1f
  2607                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2608 00005570 C3                  <1> 	retn
  2609                              <1> 	;	; rts r0 / no, return - no writing to do
  2610                              <1> writei_1: ;1:
  2611                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2612 00005571 6683F828            <1> 	cmp 	ax, 40
  2613                              <1> 		; cmp r1,$40.
  2614                              <1> 		; / does the i-node number indicate a special file?
  2615                              <1> 	;ja	dskw 
  2616                              <1> 		; bgt dskw / no, branch to standard file output
  2617                              <1> 	; 24/12/2021
  2618 00005575 7605                <1> 	jna	short writei_3
  2619 00005577 E9ED000000          <1> 	jmp	dskw
  2620                              <1> writei_3:
  2621                              <1> 	; (20/05/2015)
  2622 0000557C 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2623 0000557D 0FB6D8              <1> 	movzx	ebx, al
  2624                              <1> 	; 03/02/2022
  2625 00005580 C1E302              <1> 	shl	ebx, 2
  2626                              <1> 	;shl	bx, 2
  2627                              <1> 		; asl r1 / yes, calculate the index into the special file
  2628 00005583 81C3[87550000]      <1> 	add	ebx, writei_2 - 4
  2629 00005589 FF23                <1> 	jmp	dword [ebx]	
  2630                              <1> 		; jmp *1f-2(r1)
  2631                              <1> 		; / jump table and jump to the appropriate routine
  2632                              <1> writei_2: ;1:
  2633 0000558B [D7550000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2634                              <1> 		 ;wtty / tty; r1=2
  2635                              <1> 		 ;wppt / ppt; r1=4
  2636 0000558F [39560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2637                              <1> 		 ;wmem / mem; r1=6
  2638                              <1> 		 ;wrf0 / rf0
  2639                              <1> 		 ;wrk0 / rk0
  2640                              <1> 		 ;wtap / tap0
  2641                              <1> 		 ;wtap / tap1
  2642                              <1> 		 ;wtap / tap2
  2643                              <1> 		 ;wtap / tap3
  2644                              <1> 		 ;wtap / tap4
  2645                              <1> 		 ;wtap / tap5
  2646                              <1> 		 ;wtap / tap6
  2647                              <1> 		 ;wtap / tap7
  2648 00005593 [B15B0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2649 00005597 [B15B0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2650 0000559B [B15B0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2651 0000559F [B15B0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2652 000055A3 [B15B0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2653 000055A7 [B15B0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2654 000055AB [2A560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2655 000055AF [24560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2656                              <1> 		 ;xmtt / tty0
  2657 000055B3 [24560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2658                              <1> 		 ;xmtt / tty1
  2659 000055B7 [24560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2660                              <1> 		 ;xmtt / tty2
  2661 000055BB [24560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2662                              <1> 		 ;xmtt / tty3
  2663 000055BF [24560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2664                              <1> 		 ;xmtt / tty4
  2665 000055C3 [24560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2666                              <1> 		 ;xmtt / tty5
  2667 000055C7 [24560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2668                              <1> 		 ;xmtt / tty6
  2669 000055CB [24560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2670                              <1> 		 ;xmtt / tty7
  2671 000055CF [24560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2672                              <1> 		; / wlpr / lpr
  2673 000055D3 [24560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2674                              <1> 
  2675                              <1> wtty: ; write to console tty (write to screen)
  2676                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2677                              <1> 	; 18/11/2015
  2678                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2679                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2680                              <1> 	;
  2681                              <1> 	; Console tty output is on current video page
  2682                              <1> 	; Console tty character output procedure is changed here
  2683                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2684                              <1> 	;
  2685 000055D7 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2686 000055DE 8AA3[176C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2687 000055E4 88E0                <1> 	mov	al, ah ; 07/07/2014
  2688                              <1> wttys:	
  2689                              <1> 	; 10/10/2013
  2690 000055E6 8825[0C6F0000]      <1> 	mov 	[u.ttyn], ah
  2691                              <1> 	; 13/01/2014
  2692 000055EC FEC0                <1> 	inc	al
  2693 000055EE A2[E96E0000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2694                              <1> wtty_nc: ; 15/05/2013
  2695                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2696 000055F3 E816010000          <1> 	call	cpass
  2697                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2698                              <1> 		             ; / none go to return address in syswrite
  2699                              <1> 		; tst r1 / is character = null
  2700                              <1> 		; beq wtty / yes, get next character
  2701                              <1> 	; 10/10/2013
  2702 000055F8 7428                <1> 	jz	short wret
  2703                              <1> 	;1 : 
  2704                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2705                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2706                              <1> 		;	          / than 20
  2707                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2708                              <1> 	; 27/06/2014
  2709                              <1> wtty_1:
  2710                              <1> 	; AH = tty number
  2711                              <1> 	; AL = ASCII code of the character
  2712                              <1> 	; 15/04/2014
  2713                              <1> 	;push	ax
  2714                              <1> 	; 24/12/2021
  2715 000055FA 50                  <1> 	push	eax
  2716 000055FB E8E6090000          <1> 	call	putc ; 14/05/2013
  2717 00005600 731D                <1> 	jnc	short wtty_2
  2718                              <1> 	; 18/11/2015
  2719 00005602 E824F9FFFF          <1> 	call	idle
  2720                              <1> 	;mov	ax, [esp]
  2721                              <1> 	; 24/12/2021
  2722 00005607 8B0424              <1> 	mov	eax, [esp]
  2723 0000560A E8D7090000          <1> 	call	putc
  2724 0000560F 730E                <1> 	jnc	short wtty_2 
  2725                              <1> 	; 02/06/2014
  2726 00005611 8A25[0C6F0000]      <1> 	mov	ah, [u.ttyn]
  2727 00005617 E89CF9FFFF          <1> 	call	sleep
  2728                              <1> 	;pop	ax
  2729                              <1> 	; 24/12/2021
  2730 0000561C 58                  <1> 	pop	eax
  2731 0000561D EBDB                <1> 	jmp 	short wtty_1
  2732                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2733                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2734                              <1> 			      ; / console tty and
  2735                              <1> 		; br 	2f / place character in list; if none available
  2736                              <1> 		   	  ; / branch to put process to sleep
  2737                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2738                              <1> wtty_2:
  2739                              <1> 	; 15/04/2014
  2740                              <1> 	;pop	ax
  2741                              <1> 	; 24/12/2021
  2742 0000561F 58                  <1> 	pop	eax
  2743 00005620 EBD1                <1> 	jmp	short wtty_nc
  2744                              <1> 		; br wtty
  2745                              <1> wret:	; 10/10/2013 (20/05/2015)
  2746 00005622 58                  <1> 	pop	eax
  2747 00005623 C3                  <1> 	retn
  2748                              <1> 	;2:
  2749                              <1> 		;mov	r1,-(sp) / place character on stack
  2750                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2751                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2752                              <1> 		;br	1b / try again to place character in clist and output
  2753                              <1> 
  2754                              <1> xmtt:   ; < send/write character to tty >
  2755                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2756                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2757                              <1> 	;
  2758                              <1> 	; Retro UNIX 8086 v1 modification !
  2759                              <1> 	; 
  2760                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2761                              <1> 	;		(exactly different than this one)
  2762                              <1> 	;	was in 'u9.s' file.
  2763                              <1> 	;
  2764 00005624 2C0A                <1> 	sub 	al, 10
  2765                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2766                              <1> 	 ; 10/10/2013
  2767 00005626 88C4                <1> 	mov	ah, al
  2768                              <1> 	; 28/07/2013
  2769 00005628 EBBC                <1> 	jmp	short wttys
  2770                              <1> 
  2771                              <1> ;wppt:
  2772                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2773                              <1> ;		         / if none return to writei's calling routine
  2774                              <1> ;	jsr	r0,pptoc / output character on ppt
  2775                              <1> ;	br	wppt
  2776                              <1> wlpr:
  2777 0000562A C705[0D6F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2777 00005632 0000                <1>
  2778 00005634 E99BE4FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2779                              <1> 		;/	jsr	r0,cpass
  2780                              <1> 		;/	cmp	r0,$'a
  2781                              <1> 		;/	blo	1f
  2782                              <1> 		;/	cmp	r1,$'z
  2783                              <1> 		;/	bhi	1f
  2784                              <1> 		;/	sub	$40,r1
  2785                              <1> 		;/1:
  2786                              <1> 		;/	jsr	r0,lptoc
  2787                              <1> 		;/	br	wlpr
  2788                              <1> 		; br rmem / continue
  2789                              <1> 
  2790                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2791                              <1> 	; 17/10/2015
  2792                              <1> 	; 11/06/2015
  2793                              <1> 	; 24/05/2015
  2794                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2795                              <1> 	;
  2796 00005639 813D[12070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2796 0000563F [4E4F0000]          <1>
  2797 00005643 7415                <1>         je      short wmem_acc_err
  2798                              <1> 	;
  2799 00005645 8B35[C86E0000]      <1>         mov     esi, [u.fofp] 
  2800                              <1> wmem_1:
  2801 0000564B E8BE000000          <1> 	call	cpass
  2802                              <1> 		; jsr r0,cpass / get next character from users area of
  2803                              <1> 			     ; / core and put it in r1
  2804                              <1>         	; mov r1,-(sp) / put character on the stack
  2805                              <1> 	; 20/09/2013
  2806 00005650 74D0                <1> 	jz	short wret ; wmem_2  
  2807 00005652 8B1E                <1>         mov     ebx, [esi]
  2808                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2809 00005654 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2810                              <1> 		; inc *u.fofp / increment file offset to point to next
  2811                              <1> 			    ; / available location in file
  2812 00005656 8803                <1> 	mov	[ebx], al	
  2813                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2814                              <1> 			        ; / assigned to it
  2815 00005658 EBF1                <1> 	jmp	short wmem_1
  2816                              <1> 		; br wmem / continue
  2817                              <1> 	;1:
  2818                              <1> 	;jmp	error / ?
  2819                              <1> ;wmem_2:	
  2820                              <1> ;	; 20/09/2013
  2821                              <1> ;	pop	ax
  2822                              <1> ;	retn
  2823                              <1> 
  2824                              <1> wmem_acc_err:
  2825 0000565A C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2825 00005662 0000                <1>
  2826 00005664 E96BE4FFFF          <1> 	jmp	error
  2827                              <1> 
  2828                              <1> 
  2829                              <1> dskw: ; / write routine for non-special files
  2830                              <1> 	;
  2831                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2832                              <1> 	; 25/07/2015
  2833                              <1> 	; 16/06/2015
  2834                              <1> 	; 09/06/2015
  2835                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2836                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2837                              <1> 	;
  2838                              <1> 	; 01/08/2013 (mkdir_w check)
  2839                              <1> 
  2840                              <1> 	;push	ax ; 26/04/2013
  2841                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2842                              <1> 	; 24/12/2021
  2843 00005669 50                  <1> 	push	eax
  2844                              <1> 	; AX = inode number
  2845 0000566A E828FBFFFF          <1> 	call	iget
  2846                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2847                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2848 0000566F 8B1D[C86E0000]      <1>         mov     ebx, [u.fofp] 
  2849 00005675 8B13                <1> 	mov 	edx, [ebx]
  2850                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2851                              <1> 			       ; / in the fsp entry for this file] in r2
  2852 00005677 0315[DC6E0000]      <1> 	add 	edx, [u.count]	
  2853                              <1> 		; add u.count,r2 / no. of bytes to be written
  2854                              <1> 			       ; / + file offset is put in r2
  2855                              <1> 	; 16/06/2015        
  2856 0000567D 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2857 00005683 760F                <1> 	jna	short dskw_0
  2858 00005685 C705[0D6F0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2858 0000568D 0000                <1>
  2859 0000568F E940E4FFFF          <1> 	jmp	error
  2860                              <1> dskw_0:	
  2861 00005694 663B15[BC6B0000]    <1> 	cmp     dx, [i.size]
  2862                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2863                              <1> 		              ; / the file?
  2864 0000569B 760C                <1> 	jna	short dskw_1
  2865                              <1> 		; blos 1f / no, branch
  2866 0000569D 668915[BC6B0000]    <1>         mov     [i.size], dx
  2867                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2868                              <1> 			      ; / file offset + no. of data bytes
  2869 000056A4 E8F8FBFFFF          <1> 	call	setimod
  2870                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2871                              <1> 		          ; / modified), stuff time of modification into
  2872                              <1> 	          	  ; / core image of i-node
  2873                              <1> dskw_1: ; 1:	
  2874 000056A9 E882F9FFFF          <1> 	call	mget
  2875                              <1> 	; eAX = Block number
  2876                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2877                              <1> 			    ; /	the next data byte
  2878                              <1> 	; eax = block number
  2879 000056AE 8B1D[C86E0000]      <1> 	mov     ebx, [u.fofp]
  2880 000056B4 8B13                <1> 	mov	edx, [ebx]
  2881 000056B6 81E2FF010000        <1> 	and	edx, 1FFh  
  2882                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2883 000056BC 750C                <1> 	jnz	short dskw_2
  2884                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2885                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2886 000056BE 813D[DC6E0000]0002- <1> 	cmp	dword [u.count], 512
  2886 000056C6 0000                <1>
  2887                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2888                              <1> 				  ; / an entire block? (i.e., no. of
  2889 000056C8 7305                <1> 	jnb	short dskw_3
  2890                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2891                              <1> 			; / Yes, branch. Don't have to read block
  2892                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2893                              <1>    		; / overwritten).
  2894 000056CA E8A8050000          <1> 	call	dskrd
  2895                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2896                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2897                              <1> dskw_3: ; 3:
  2898                              <1> 	; eAX (r1) = block/sector number
  2899 000056CF E815060000          <1> 	call	wslot
  2900                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2901                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2902 000056D4 803D[1F6F0000]00    <1> 	cmp	byte [u.kcall], 0
  2903 000056DB 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2904                              <1> 	;
  2905 000056DD 66833D[1D6F0000]00  <1> 	cmp	word [u.pcount], 0
  2906 000056E5 7705                <1> 	ja	short dskw_5
  2907                              <1> dskw_4:
  2908                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2909 000056E7 E810FEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2910                              <1> dskw_5:
  2911                              <1> 	; eBX (r5) = system (I/O) buffer address
  2912 000056EC E87D000000          <1> 	call	sioreg
  2913                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2914                              <1> 			     ; / r1 = address of data, r2 points to location
  2915                              <1> 			     ; / in buffer in which to start writing data
  2916                              <1> 	; eSI = file (user data) offset
  2917                              <1> 	; eDI = sector (I/O) buffer offset
  2918                              <1> 	; eCX = byte count
  2919                              <1> 	;
  2920 000056F1 F3A4                <1>   	rep	movsb
  2921                              <1> 		; movb (r1 )+,(r2)+ 
  2922                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2923                              <1> 		; dec r3 / decrement no. of bytes to be written
  2924                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2925                              <1> 	; 25/07/2015
  2926                              <1> 	; eax = remain bytes in buffer
  2927                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2928 000056F3 09C0                <1> 	or	eax, eax
  2929 000056F5 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2930                              <1> dskw_6:
  2931 000056F7 E809060000          <1> 	call	dskwr
  2932                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2933 000056FC 833D[DC6E0000]00    <1>         cmp     dword [u.count], 0
  2934                              <1> 		; tst u.count / any more data to write?
  2935 00005703 77A4                <1> 	ja	short dskw_1
  2936                              <1> 		; bne 1b / yes, branch
  2937                              <1> 	; 03/08/2013
  2938 00005705 C605[1F6F0000]00    <1> 	mov	byte [u.kcall], 0
  2939                              <1> 	; 20/09/2013 (;;)
  2940                              <1> 	;pop	ax
  2941                              <1> 	; 24/12/2021
  2942 0000570C 58                  <1> 	pop	eax
  2943 0000570D C3                  <1> 	retn
  2944                              <1> 	;;jmp 	short dskw_ret 
  2945                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2946                              <1> 
  2947                              <1> cpass: ; / get next character from user area of core and put it in r1
  2948                              <1> 	; 18/10/2015
  2949                              <1> 	; 10/10/2015
  2950                              <1> 	; 10/07/2015
  2951                              <1> 	; 02/07/2015
  2952                              <1> 	; 01/07/2015
  2953                              <1> 	; 24/06/2015
  2954                              <1> 	; 08/06/2015
  2955                              <1> 	; 04/06/2015
  2956                              <1> 	; 20/05/2015
  2957                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2958                              <1> 	;
  2959                              <1> 	; INPUTS -> 
  2960                              <1> 	;     [u.base] = virtual address in user area
  2961                              <1> 	;     [u.count] = byte count (max.)
  2962                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2963                              <1> 	; OUTPUTS -> 
  2964                              <1> 	;     AL = the character which is pointed by [u.base]
  2965                              <1> 	;     zf = 1 -> transfer count has been completed	
  2966                              <1>         ;
  2967                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  2968                              <1> 	;
  2969                              <1> 	;
  2970 0000570E 833D[DC6E0000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2971                              <1> 		; tst u.count / have all the characters been transferred
  2972                              <1> 			    ; / (i.e., u.count, # of chars. left
  2973 00005715 763F                <1> 	jna	short cpass_3
  2974                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2975 00005717 FF0D[DC6E0000]      <1> 	dec	dword [u.count]
  2976                              <1> 		; dec u.count / no, decrement u.count
  2977                              <1>         ; 19/05/2015 
  2978                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2979                              <1> 	;		      to physical address
  2980 0000571D 66833D[1D6F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2981                              <1> 			     ; 1-4095 --> use previous physical base address
  2982                              <1> 			     ; in [u.pbase]
  2983 00005725 770E                <1> 	ja	short cpass_1
  2984                              <1> 	; 02/07/2015
  2985 00005727 833D[156F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  2986 0000572E 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  2987                              <1> 	; 08/06/2015 - 10/07/2015
  2988 00005730 E8C7FDFFFF          <1> 	call	trans_addr_r
  2989                              <1> cpass_1:
  2990                              <1> 	; 02/07/2015
  2991                              <1> 	; 24/06/2015
  2992 00005735 66FF0D[1D6F0000]    <1> 	dec	word [u.pcount]
  2993                              <1> cpass_2: 
  2994                              <1> 	; 10/10/2015
  2995                              <1> 	; 02/07/2015
  2996 0000573C 8B15[196F0000]      <1> 	mov	edx, [u.pbase]
  2997 00005742 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  2998                              <1> 		; movb *u.base,r1 / take the character pointed to 
  2999                              <1> 				; / by u.base and put it in r1
  3000 00005744 FF05[E06E0000]      <1> 	inc	dword [u.nread]
  3001                              <1> 		; inc u.nread / increment no. of bytes transferred
  3002 0000574A FF05[D86E0000]      <1> 	inc	dword [u.base]
  3003                              <1> 		; inc u.base / increment the buffer address to point to the
  3004                              <1> 			   ; / next byte
  3005 00005750 FF05[196F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3006                              <1> cpass_3:
  3007 00005756 C3                  <1> 	retn
  3008                              <1> 		; rts	r0 / next byte
  3009                              <1> 	; 1: 
  3010                              <1> 		; mov (sp)+,r0 
  3011                              <1> 		         ; / put return address of calling routine into r0
  3012                              <1> 		; mov (sp)+,r1 / i-number in r1
  3013                              <1> 		; rts r0 / non-local return
  3014                              <1> cpass_k:
  3015                              <1> 	; 02/07/2015
  3016                              <1> 	; The caller is os kernel 
  3017                              <1> 	; (get sysexec arguments from kernel's memory space)
  3018                              <1> 	;
  3019 00005757 8B1D[D86E0000]      <1> 	mov	ebx, [u.base]
  3020 0000575D 66C705[1D6F0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3020 00005765 10                  <1>
  3021 00005766 891D[196F0000]      <1> 	mov	[u.pbase], ebx
  3022 0000576C EBCE                <1> 	jmp	short cpass_2
  3023                              <1> 	
  3024                              <1> sioreg: 
  3025                              <1> 	; 25/07/2015
  3026                              <1> 	; 18/07/2015
  3027                              <1> 	; 02/07/2015
  3028                              <1> 	; 17/06/2015
  3029                              <1> 	; 09/06/2015
  3030                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3031                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3032                              <1> 	;
  3033                              <1> 	; INPUTS -> 
  3034                              <1> 	;     eBX = system buffer (data) address (r5)
  3035                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3036                              <1> 	;     [u.base] = virtual address of the user buffer
  3037                              <1> 	;     [u.pbase] = physical address of the user buffer
  3038                              <1> 	;     [u.count] = byte count
  3039                              <1> 	;     [u.pcount] = byte count within page frame 			
  3040                              <1> 	; OUTPUTS -> 
  3041                              <1> 	;     eSI = user data offset (r1)
  3042                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3043                              <1> 	;     eCX = byte count (r3)
  3044                              <1> 	;     EAX = remain bytes after byte count within page frame
  3045                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3046                              <1>         ;
  3047                              <1> 	; ((Modified registers:  EDX))
  3048                              <1>  
  3049 0000576E 8B35[C86E0000]      <1>         mov     esi, [u.fofp]
  3050 00005774 8B3E                <1>         mov     edi, [esi]
  3051                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3052 00005776 89F9                <1> 	mov	ecx, edi
  3053                              <1> 		; mov r2,r3 / and also to r3
  3054 00005778 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3055                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3056 0000577E 81E7FF010000        <1> 	and	edi, 1FFh
  3057                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3058 00005784 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3059                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3060                              <1> 			  ; / where data is to be placed
  3061                              <1>                 ; mov u.base,r1 / address of data is in r1
  3062 00005786 F7D9                <1> 	neg	ecx
  3063                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3064                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3065 00005788 3B0D[DC6E0000]      <1> 	cmp	ecx, [u.count]
  3066                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3067                              <1> 			       ; / to be written to the file
  3068 0000578E 7606                <1> 	jna	short sioreg_0
  3069                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3070                              <1> 			 ; / in the file block as the number to be written
  3071 00005790 8B0D[DC6E0000]      <1> 	mov	ecx, [u.count]
  3072                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3073                              <1> 			       ; / bytes as the number to be written
  3074                              <1> sioreg_0:
  3075                              <1> 	; 17/06/2015
  3076 00005796 803D[1F6F0000]00    <1> 	cmp	byte [u.kcall], 0 
  3077 0000579D 7613                <1> 	jna	short sioreg_1
  3078                              <1> 	; 25/07/2015
  3079                              <1> 	; the caller is 'mkdir' or 'namei'
  3080 0000579F A1[D86E0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3081 000057A4 A3[196F0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3082 000057A9 66890D[1D6F0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3083 000057B0 EB0B                <1> 	jmp	short sioreg_2
  3084                              <1> sioreg_1:
  3085                              <1> 	; 25/07/2015
  3086                              <1> 	; 18/07/2015
  3087                              <1> 	; 09/06/2015 
  3088 000057B2 0FB715[1D6F0000]    <1> 	movzx	edx, word [u.pcount]
  3089                              <1> 		; ecx and [u.pcount] are always > 0, here
  3090 000057B9 39D1                <1> 	cmp	ecx, edx	
  3091 000057BB 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3092                              <1> sioreg_2: ; 2:
  3093 000057BD 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3094                              <1> sioreg_3:
  3095 000057BF 010D[E06E0000]      <1> 	add 	[u.nread], ecx
  3096                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3097                              <1> 			         ; / during write is put into u.nread
  3098 000057C5 290D[DC6E0000]      <1> 	sub 	[u.count], ecx
  3099                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3100                              <1> 			       ; / must be written or read
  3101 000057CB 010D[D86E0000]      <1> 	add 	[u.base], ecx
  3102                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3103                              <1> 			      ; / data bytes
  3104 000057D1 010E                <1>         add 	[esi], ecx 
  3105                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3106                              <1> 			       ; / + old file offset
  3107                              <1> 	; 25/07/2015
  3108 000057D3 8B35[196F0000]      <1> 	mov	esi, [u.pbase]
  3109 000057D9 66290D[1D6F0000]    <1> 	sub	[u.pcount], cx
  3110 000057E0 010D[196F0000]      <1> 	add	[u.pbase], ecx
  3111 000057E6 C3                  <1>         retn
  3112                              <1> 		; rts r0
  3113                              <1> 		; transfer count > [u.pcount]
  3114                              <1> sioreg_4:
  3115                              <1> 	; 25/07/2015
  3116                              <1> 	; transfer count > [u.pcount] 
  3117                              <1> 	; (ecx > edx)
  3118 000057E7 89C8                <1> 	mov	eax, ecx
  3119 000057E9 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3120 000057EB 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3121 000057ED EBD0                <1> 	jmp	short sioreg_3
  2094                                  %include 'u7.s'        ; 18/04/2015
  2095                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS7.INC
  2096                              <1> ; Last Modification: 26/02/2022
  2097                              <1> ; ----------------------------------------------------------------------------
  2098                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2099                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2100                              <1> ;
  2101                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2102                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2103                              <1> ; <Bell Laboratories (17/3/1972)>
  2104                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2105                              <1> ;
  2106                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2107                              <1> ;
  2108                              <1> ; ****************************************************************************
  2109                              <1> 
  2110                              <1> sysmount: ; / mount file system; args special; name
  2111                              <1> 	; 09/02/2022
  2112                              <1> 	; 08/02/2022
  2113                              <1> 	; 07/02/2022
  2114                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2115                              <1> 	; 14/11/2015
  2116                              <1> 	; 24/10/2015
  2117                              <1> 	; 13/10/2015
  2118                              <1> 	; 10/07/2015
  2119                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2120                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2121                              <1> 	;
  2122                              <1> 	; 'sysmount' anounces to the system that a removable 
  2123                              <1> 	; file system has been mounted on a special file.
  2124                              <1> 	; The device number of the special file is obtained via
  2125                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2126                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2127                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2128                              <1> 	; to read file system into core, i.e. the first block on the
  2129                              <1> 	; mountable file system is read in. This block is super block
  2130                              <1> 	; for the file system. This call is super user restricted.	
  2131                              <1> 	;
  2132                              <1> 	; Calling sequence:
  2133                              <1> 	;	sysmount; special; name
  2134                              <1> 	; Arguments:
  2135                              <1> 	;	special - pointer to name of special file (device)
  2136                              <1> 	;	name -  pointer to name of the root directory of the
  2137                              <1> 	;		newly mounted file system. 'name' should 
  2138                              <1> 	;		always be a directory.
  2139                              <1> 	; Inputs: - 
  2140                              <1> 	; Outputs: -
  2141                              <1> 	; ...............................................................
  2142                              <1> 	;				
  2143                              <1> 	; Retro UNIX 8086 v1 modification: 
  2144                              <1> 	;       'sysmount' system call has two arguments; so,
  2145                              <1> 	;	* 1st argument, special is pointed to by BX register
  2146                              <1> 	;	* 2nd argument, name is in CX register
  2147                              <1> 	;
  2148                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2149                              <1> 	;	       already modified for IBM PC compatibility and 
  2150                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2151                              <1> 	
  2152                              <1> 	;call	arg2
  2153                              <1> 		; jsr r0,arg2 / get arguments special and name
  2154 000057EF 891D[D06E0000]      <1> 	mov	[u.namep], ebx
  2155                              <1> 	; 09/02/2022
  2156                              <1> 	;push	ecx ; directory name
  2157 000057F5 66833D[A46E0000]00  <1> 	cmp	word [mnti], 0
  2158                              <1> 		; tst mnti / is the i-number of the cross device file
  2159                              <1> 			 ; / zero?
  2160                              <1> 	;;ja	error
  2161                              <1>         	; bne errora / no, error
  2162                              <1> 	;ja	sysmnt_err0
  2163                              <1> 	; 11/01/2022
  2164 000057FD 7605                <1> 	jna	short sysmnt_0
  2165 000057FF E907010000          <1> 	jmp	sysmnt_err0
  2166                              <1> sysmnt_0:
  2167                              <1> 	; 09/02/2022
  2168 00005804 51                  <1> 	push	ecx ; directory name
  2169 00005805 E8E9000000          <1> 	call	getspl
  2170                              <1> 		; jsr r0,getspl / get special files device number in r1
  2171                              <1> 	; 09/02/2022
  2172 0000580A 8F05[D06E0000]      <1> 	pop	dword [u.namep] ; directory name
  2173                              <1> 	; 13/10/2015
  2174                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2175                              <1> 	; 11/01/2022
  2176 00005810 29DB                <1> 	sub	ebx, ebx
  2177 00005812 88C3                <1> 	mov	bl, al
  2178 00005814 F683[3A660000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2179 0000581B 750F                <1> 	jnz	short sysmnt_1
  2180                              <1> sysmnt_err1:
  2181 0000581D C705[0D6F0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2181 00005825 0000                <1>
  2182 00005827 E9A8E2FFFF          <1> 	jmp	error
  2183                              <1> sysmnt_1:
  2184                              <1> 	; 09/02/2022
  2185                              <1> 	;pop	dword [u.namep]
  2186                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2187                              <1> 				  ; / on the device
  2188                              <1> 	; 14/11/2015
  2189 0000582C 53                  <1> 	push	ebx ; 13/10/2015
  2190                              <1> 		; mov r1,-(sp) / save the device number
  2191                              <1>         ;
  2192 0000582D E8A0F1FFFF          <1> 	call	namei
  2193                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2194                              <1> 		       ; ax = 0 -> file not found 	
  2195                              <1> 	;jz	error
  2196                              <1> 	;jc	error
  2197                              <1> 		; jsr r0,namei / get the i-number of the file
  2198                              <1>                	; br errora
  2199 00005832 730F                <1> 	jnc	short sysmnt_2
  2200                              <1> sysmnt_err2:
  2201 00005834 C705[0D6F0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2201 0000583C 0000                <1>
  2202 0000583E E991E2FFFF          <1> 	jmp	error
  2203                              <1> sysmnt_2:	
  2204 00005843 66A3[A46E0000]      <1> 	mov	[mnti], ax
  2205                              <1>         	; mov r1,mnti / put it in mnti
  2206                              <1> 	; 11/01/2022
  2207 00005849 BB[787D0000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2208                              <1> sysmnt_3: ;1:
  2209                              <1>         ;cmp	byte [ebx+1], 0
  2210                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2211                              <1> 			   ; / dismountable device set?
  2212                              <1>         ;jna	short sysmnt_4		
  2213                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2214                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2215                              <1> 	;jmp	short sysmnt_3
  2216                              <1> sysmnt_4:   
  2217 0000584E 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2218 0000584F A2[A16E0000]        <1> 	mov	[mdev], al
  2219                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2220 00005854 8803                <1> 	mov	[ebx], al
  2221                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2222                              <1> 			      ; / of the I/O queue entry
  2223                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2224                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2225 00005856 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2226                              <1> 		; bis $2000,sb1 / set the read bit
  2227                              <1> 	; Retro UNIX 386 v1 modification : 
  2228                              <1> 	;	32 bit block number at buffer header offset 4
  2229 0000585B C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2230 00005862 E8E9050000          <1> 	call 	diskio
  2231 00005867 7345                <1> 	jnc	short sysmnt_5
  2232 00005869 31C0                <1> 	xor 	eax, eax
  2233 0000586B 66A3[A46E0000]      <1> 	mov	[mnti], ax ; 0
  2234 00005871 A2[A16E0000]        <1> 	mov	[mdev], al ; 0
  2235                              <1> 	;mov	[cdev], al ; 0
  2236                              <1> 	; 08/02/2022
  2237 00005876 803D[206F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2238 0000587D 7508                <1> 	jne	short sysmnt_err3
  2239                              <1> 	; yes, clear [u.brwdev] for next check
  2240                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2241 0000587F FE05[206F0000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2242 00005885 EB0A                <1> 	jmp	short sysmnt_err4
  2243                              <1> sysmnt_err3:	; 08/02/2022
  2244                              <1> 	; no, set [u.error] to disk read error
  2245 00005887 C705[0D6F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2245 0000588F 0000                <1>
  2246                              <1> sysmnt_err4:
  2247                              <1> 	; 08/02/2022
  2248                              <1> 	; 14/11/2015
  2249 00005891 FEC8                <1> 	dec 	al
  2250 00005893 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2251 00005895 FEC0                <1> 	inc	al
  2252 00005897 48                  <1> 	dec	eax
  2253 00005898 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2254 0000589B E934E2FFFF          <1> 	jmp	error
  2255                              <1> sysmnt_invd:
  2256                              <1> 	; 08/02/2022
  2257 000058A0 C705[0D6F0000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2257 000058A8 0000                <1>
  2258                              <1> 				 ;'invalid fs/superblock !' error
  2259 000058AA 30C0                <1> 	xor	al, al
  2260 000058AC EBE3                <1> 	jmp	short sysmnt_err4	
  2261                              <1> 
  2262                              <1> sysmnt_5:
  2263                              <1> 	; 08/02/2022
  2264                              <1> 	; 11/01/2022 (BugFix)
  2265                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2266                              <1> 	; (Following check is needed to prevent mounting an
  2267                              <1> 	; invalid file system (invalid super block).
  2268                              <1> 	; 
  2269 000058AE 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2270 000058B1 C0E002              <1> 	shl	al, 2 ; 4*index
  2271 000058B4 8B88[1E660000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2272 000058BA C1E903              <1> 	shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2273                              <1> 	; ecx = number of free map bytes (required)
  2274                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2275 000058BD 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2276                              <1> 	; edx = number of free blocks map bytes
  2277                              <1> 	;shl	edx, 3 ; convert free map bytes to free map bits
  2278                              <1> 	; 07/02/2022
  2279                              <1> 	;xor	al, al ; 08/02/2022
  2280 000058C1 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2281                              <1> 			 ; (in sectors), if they are not equal
  2282                              <1> 			 ; the disk to be mounted is an...	
  2283 000058C3 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2284                              <1> 			 ; (which has not got a valid super block)
  2285                              <1> 	;
  2286 000058C5 C6430100            <1> 	mov	byte [ebx+1], 0
  2287                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2288                              <1> ;sysmnt_6: ;1:
  2289                              <1> 	;;cmp	byte [sb1+1], 0
  2290                              <1> 		; tstb sb1+1 / done reading?
  2291                              <1>    	;;jna	sysret
  2292                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2293                              <1> 	;;jmp	short sysmnt_6
  2294                              <1> 		; bne 1b / no, wait
  2295                              <1>         	; br sysreta / yes
  2296 000058C9 E926E2FFFF          <1> 	jmp	sysret
  2297                              <1> 
  2298                              <1> sysumount: ; / special dismount file system
  2299                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2300                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2301                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2302                              <1> 	;
  2303                              <1> 	; 04/11/2013
  2304                              <1> 	; 09/07/2013
  2305                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2306                              <1> 	; indicated as an argument is no longer contain a removable
  2307                              <1> 	; file system. 'getspl' gets the device number of the special
  2308                              <1> 	; file. If no file system was mounted on that device an error
  2309                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2310                              <1> 	; to 'sysret'.
  2311                              <1> 	;
  2312                              <1> 	; Calling sequence:
  2313                              <1> 	;	sysmount; special
  2314                              <1> 	; Arguments:
  2315                              <1> 	;	special - special file to dismount (device)
  2316                              <1> 	;
  2317                              <1> 	; Inputs: - 
  2318                              <1> 	; Outputs: -
  2319                              <1> 	; ...............................................................
  2320                              <1> 	;				
  2321                              <1> 	; Retro UNIX 8086 v1 modification: 
  2322                              <1> 	;       'sysumount' system call has one argument; so,
  2323                              <1> 	;	* Single argument, special is pointed to by BX register
  2324                              <1> 	;
  2325                              <1> 	
  2326                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2327                              <1> 	;call	arg
  2328                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2329 000058CE 891D[D06E0000]      <1>         mov	[u.namep], ebx
  2330 000058D4 E81A000000          <1> 	call	getspl
  2331                              <1> 		; jsr r0,getspl / get the device number in r1
  2332 000058D9 3A05[A16E0000]      <1> 	cmp	al, [mdev]
  2333                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2334 000058DF 752A                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2335                              <1> 	;jne	error
  2336                              <1>         	; bne errora / no error
  2337 000058E1 30C0                <1> 	xor	al, al ; ah = 0
  2338                              <1> sysumnt_0: ;1:
  2339                              <1>      	; 11/01/2022
  2340                              <1> 	;cmp 	[sb1+1], al ; 0
  2341                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2342                              <1> 	;		   ; / (inhibit bit set)?
  2343                              <1> 	;jna	short sysumnt_1		
  2344                              <1> 	;	; bne 1b / yes, wait
  2345                              <1> 	;call	idle ; (wait for hardware interrupt)
  2346                              <1> 	;jmp	short sysumnt_0
  2347                              <1> sysumnt_1:        
  2348 000058E3 A2[A16E0000]        <1> 	mov	[mdev], al ; 0
  2349                              <1> 	     	; clr mntd / no, clear these
  2350 000058E8 66A3[A46E0000]      <1>    	mov	[mnti], ax ; 0
  2351                              <1>         	; clr mnti
  2352 000058EE E901E2FFFF          <1>         jmp	sysret
  2353                              <1> 		; br sysreta / return
  2354                              <1> 
  2355                              <1> getspl: ; / get device number from a special file name
  2356 000058F3 E8DAF0FFFF          <1> 	call	namei
  2357                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2358                              <1> 		       ; ax = 0 -> file not found 	
  2359                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2360                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2361 000058F8 7305                <1> 	jnc	short getspl_0
  2362 000058FA E935FFFFFF          <1> 	jmp	sysmnt_err2 ; 'file not found !' error
  2363                              <1> getspl_0:
  2364                              <1> 	;jz	error
  2365                              <1> 	;jc	error
  2366                              <1> 		; jsr r0,namei / get the i-number of the special file
  2367                              <1>                 ; br errora / no such file
  2368 000058FF 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2369                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2370                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2371 00005903 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2372                              <1> 	;jc	error
  2373                              <1> 		; ble errora / less than 0?  yes, error
  2374 00005905 6683F805            <1>         cmp	ax, 5 ;
  2375                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2376                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2377                              <1> 	;;ja	error
  2378                              <1> 		; bgt errora / yes, error
  2379                              <1> 	; 11/01/2022
  2380 00005909 760F                <1> 	jna	short getspl_retn
  2381                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2382                              <1> ;iopen_retn:
  2383                              <1> ;	retn
  2384                              <1> 		; rts r0 / return with device number in r1
  2385                              <1> sysmnt_err0:
  2386 0000590B C705[0D6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2386 00005913 0000                <1>
  2387 00005915 E9BAE1FFFF          <1> 	jmp	error
  2388                              <1> 
  2389                              <1> getspl_retn:
  2390                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2391                              <1> 	; 11/01/2022
  2392                              <1> iopen_retn:
  2393 0000591A C3                  <1> 	retn
  2394                              <1> 
  2395                              <1> iopen:
  2396                              <1> 	; 11/01/2022
  2397                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2398                              <1> 	; 19/05/2015
  2399                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2400                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2401                              <1> 	;
  2402                              <1> 	; open file whose i-number is in r1
  2403                              <1> 	; 
  2404                              <1> 	; INPUTS ->
  2405                              <1> 	;    r1 - inode number
  2406                              <1> 	; OUTPUTS ->
  2407                              <1> 	;    file's inode in core	
  2408                              <1> 	;    r1 - inode number (positive)
  2409                              <1> 	;
  2410                              <1> 	; ((AX = R1))
  2411                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2412                              <1> 	;        
  2413                              <1> ; / open file whose i-number is in r1
  2414 0000591B F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2415                              <1> 		; tst r1 / write or read access?
  2416 0000591E 7568                <1>         jnz	short iopen_2
  2417                              <1> 		; blt 2f / write, go to 2f
  2418 00005920 B202                <1> 	mov	dl, 2 ; read access
  2419 00005922 E844F9FFFF          <1> 	call	access
  2420                              <1>         	; jsr r0,access; 2 
  2421                              <1> 	; / get inode into core with read access
  2422                              <1> 	; DL=2
  2423                              <1> iopen_0:
  2424 00005927 6683F828            <1>         cmp	ax, 40
  2425                              <1> 		; cmp r1,$40. / is it a special file
  2426 0000592B 77ED                <1>         ja	short iopen_retn
  2427                              <1> 		; bgt  3f / no. 3f
  2428 0000592D 50                  <1> 	push	eax ; 08/01/2022
  2429                              <1> 	;push	ax
  2430                              <1> 		; mov r1,-(sp) / yes, figure out
  2431 0000592E 0FB6D8              <1> 	movzx	ebx, al
  2432 00005931 C0E302              <1> 	shl	bl, 2 ; * 4 ; 08/01/2022
  2433                              <1> 	;shl	bx, 2
  2434                              <1> 		; asl r1
  2435 00005934 81C3[38590000]      <1>         add     ebx, iopen_1 - 4
  2436 0000593A FF23                <1> 	jmp	dword [ebx]
  2437                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2438                              <1> iopen_1: ; 1:
  2439 0000593C [A0590000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2440                              <1>  		 ;otty / tty ; r1=2
  2441                              <1>         	 ;oppt / ppt ; r1=4
  2442 00005940 [5C5A0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2443                              <1> 		 ;sret / mem ; r1=6
  2444                              <1> 		 ;sret / rf0
  2445                              <1>         	 ;sret / rk0
  2446                              <1>         	 ;sret / tap0
  2447                              <1>         	 ;sret / tap1
  2448                              <1>         	 ;sret / tap2
  2449                              <1>         	 ;sret / tap3
  2450                              <1>         	 ;sret / tap4
  2451                              <1>         	 ;sret / tap5
  2452                              <1>         	 ;sret / tap6
  2453                              <1>         	 ;sret / tap7
  2454 00005944 [5C5A0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2455 00005948 [5C5A0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2456 0000594C [5C5A0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2457 00005950 [5C5A0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2458 00005954 [5C5A0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2459 00005958 [5C5A0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2460                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2461 0000595C [5C5A0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2462 00005960 [B1590000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2463                              <1> 		 ;ocvt / tty0
  2464 00005964 [B1590000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2465                              <1> 		 ;ocvt / tty1
  2466 00005968 [B1590000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2467                              <1> 		 ;ocvt / tty2
  2468 0000596C [B1590000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2469                              <1> 		 ;ocvt / tty3
  2470 00005970 [B1590000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2471                              <1> 		 ;ocvt / tty4
  2472 00005974 [B1590000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2473                              <1> 		 ;ocvt / tty5
  2474 00005978 [B1590000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2475                              <1> 		 ;ocvt / tty6
  2476 0000597C [B1590000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2477                              <1> 		 ;ocvt / tty7
  2478 00005980 [B1590000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2479                              <1> 		 ;error / crd
  2480 00005984 [B1590000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2481                              <1> 
  2482                              <1> iopen_2: ; 2: / check open write access
  2483 00005988 66F7D8              <1> 	neg	ax
  2484                              <1> 		;neg r1 / make inode number positive
  2485 0000598B B201                <1> 	mov	dl, 1 ; write access
  2486 0000598D E8D9F8FFFF          <1> 	call	access
  2487                              <1> 		;jsr r0,access; 1 / get inode in core
  2488                              <1> 	; DL=1
  2489                              <1> 	; 11/01/2022
  2490 00005992 F605[B96B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2491                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2492                              <1>  		; bit $40000,i.flgs / is it a directory?
  2493 00005999 748C                <1> 	jz	short iopen_0
  2494                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2495                              <1> 	;jmp	error ; permission denied !
  2496 0000599B E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2497                              <1> 	;;jnz	error		
  2498                              <1>        		; bne 2f / yes, transfer (error)
  2499                              <1>         ;;jmp	short iopen_0
  2500                              <1> 	;cmp	ax, 40
  2501                              <1> 		; cmp r1,$40. / no, is it a special file?
  2502                              <1>         ;ja	short iopen_2
  2503                              <1> 		; bgt 3f / no, return
  2504                              <1> 	;push	ax
  2505                              <1> 		; mov r1,-(sp) / yes
  2506                              <1> 	;movzx	ebx, al
  2507                              <1> 	;shl	bx, 1
  2508                              <1> 		; asl r1
  2509                              <1> 	;add	ebx, ipen_3 - 2
  2510                              <1> 	;jmp	dword [ebx]
  2511                              <1> 		; jmp *1f-2(r1) / figure out 
  2512                              <1> 			; / which special file it is and transfer
  2513                              <1> ;iopen_3: ; 1:
  2514                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2515                              <1>  		 ;otty / tty ; r1=2
  2516                              <1>         	 ;leadr / ppt ; r1=4
  2517                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2518                              <1> 		 ;sret / mem ; r1=6
  2519                              <1> 		 ;sret / rf0
  2520                              <1>         	 ;sret / rk0
  2521                              <1>         	 ;sret / tap0
  2522                              <1>         	 ;sret / tap1
  2523                              <1>         	 ;sret / tap2
  2524                              <1>         	 ;sret / tap3
  2525                              <1>         	 ;sret / tap4
  2526                              <1>         	 ;sret / tap5
  2527                              <1>         	 ;sret / tap6
  2528                              <1>         	 ;sret / tap7
  2529                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2530                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2531                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2532                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2533                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2534                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2535                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2536                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2537                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2538                              <1> 		 ;ocvt / tty0
  2539                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2540                              <1> 		 ;ocvt / tty1
  2541                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2542                              <1> 		 ;ocvt / tty2
  2543                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2544                              <1> 		 ;ocvt / tty3
  2545                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2546                              <1> 		 ;ocvt / tty4
  2547                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2548                              <1> 		 ;ocvt / tty5
  2549                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2550                              <1> 		 ;ocvt / tty6
  2551                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2552                              <1> 		 ;ocvt / tty7
  2553                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2554                              <1> 		 ;/ ejec / lpr
  2555                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2556                              <1> 
  2557                              <1> otty: ;/ open console tty for reading or writing
  2558                              <1> 	; 26/02/2022
  2559                              <1> 	; 09/02/2022
  2560                              <1> 	; 06/02/2022
  2561                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2562                              <1> 	; 16/11/2015
  2563                              <1> 	; 12/11/2015
  2564                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2565                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2566                              <1> 	; 16/07/2013
  2567                              <1> 	; Retro UNIX 8086 v1 modification:
  2568                              <1> 	;  If a tty is open for read or write by
  2569                              <1> 	;     a process (u.uno), only same process can open
  2570                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2571                              <1> 	;
  2572                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2573                              <1> 	;
  2574 000059A0 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2575 000059A7 8A83[176C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2576                              <1> 	; 13/01/2014
  2577                              <1> 	;jmp	short ottyp
  2578                              <1> 	; 26/02/2022
  2579 000059AD 88C4                <1> 	mov	ah, al
  2580 000059AF EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2581                              <1> ocvt:
  2582 000059B1 2C0A                <1> 	sub	al, 10
  2583                              <1> ;ottyp:	; (call from sysstty)
  2584                              <1> 	; 08/01/2022
  2585 000059B3 31DB                <1> 	xor	ebx, ebx
  2586                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2587                              <1> 	; 26/02/2022
  2588 000059B5 B4FF                <1> 	mov	ah, 0FFh
  2589                              <1> ottypc:
  2590                              <1> 	; 26/02/2022
  2591                              <1> 	; 09/02/2022
  2592                              <1> 	; 08/01/2022
  2593                              <1> 	; 16/11/2015
  2594                              <1> 	; 12/11/2015
  2595                              <1> 	; 18/05/2015 (32 bit modifications)
  2596                              <1> 	; 06/12/2013 - 13/07/2014
  2597 000059B7 88C6                <1> 	mov	dh, al ; tty number
  2598                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2599                              <1> 	; 08/01/2022
  2600 000059B9 88C3                <1> 	mov	bl, al
  2601 000059BB D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2602                              <1> 	; 26/01/2014	
  2603 000059BD 81C3[446B0000]      <1> 	add 	ebx, ttyl
  2604 000059C3 668B0B              <1> 	mov 	cx, [ebx]
  2605                              <1> 		   ; CL = lock value (0 or process number)
  2606                              <1> 		   ; CH = open count 
  2607 000059C6 20C9                <1> 	and 	cl, cl
  2608                              <1> 	; 13/01/2014
  2609                              <1> 	;jz 	short otty_ret
  2610                              <1> 	; 08/01/2022
  2611 000059C8 7447                <1> 	jz 	short ottys_0
  2612                              <1> 	;
  2613                              <1> 	; 16/11/2015
  2614 000059CA 3A0D[076F0000]      <1> 	cmp 	cl, [u.uno]
  2615 000059D0 7472                <1> 	je	short ottys_3
  2616                              <1> 	;
  2617                              <1> 	;
  2618                              <1> 	; 26/02/2022
  2619                              <1> 	; (is it the console tty of the current process?)
  2620                              <1> 	; ((fast check/permit for console tty open function))
  2621 000059D2 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2622 000059D4 746E                <1> 	je	short ottys_3 ; bypass parent process check
  2623                              <1> 	;
  2624                              <1> 	; 26/02/2022
  2625                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2626                              <1> 	;shl 	bl, 1
  2627                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2628                              <1> 	;;movzx ebx, byte [u.uno]
  2629                              <1> 	;mov	bl, [u.uno]
  2630                              <1> 	;shl 	bl, 1
  2631                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2632                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2633                              <1> 	; 26/02/2022 (BugFix) ; *
  2634 000059D6 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2635 000059D9 D1E6                <1> 	shl 	esi, 1
  2636 000059DB 668B86[D66B0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2637 000059E2 96                  <1> 	xchg	esi, eax
  2638 000059E3 A0[076F0000]        <1> 	mov	al, [u.uno]
  2639 000059E8 D0E0                <1> 	shl 	al, 1
  2640 000059EA 663BB0[F66B0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2641 000059F1 7451                <1> 	je 	short ottys_3 ; *
  2642                              <1> 	; 26/02/2022
  2643                              <1> 	; check console tty of the process
  2644                              <1> 	; (open permission must be given if the -requested- tty is
  2645                              <1> 	;  console tty of current process)
  2646 000059F3 D0E8                <1> 	shr	al, 1
  2647 000059F5 38B0[176C0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2648 000059FB 7447                <1> 	je 	short ottys_3
  2649                              <1> 	;
  2650                              <1> 	; the tty is locked by another process
  2651                              <1> 	; except the parent process (p.ppid)
  2652                              <1>         ;
  2653                              <1> 	; 09/02/2022
  2654                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2655                              <1> 	;		; permission denied ! error
  2656                              <1> otty_err: ; 13/01/2014
  2657                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2658                              <1> 	;;jnz	error
  2659                              <1> 	; 05/12/2021
  2660                              <1> 	;jz	short otty_stc_retn
  2661                              <1> 	;jmp	error
  2662                              <1> 	; 09/02/2022
  2663 000059FD 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2664 00005A00 725B                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2665                              <1> 	; iopen (dl=1 or dl=2)
  2666 00005A02 C705[0D6F0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2666 00005A0A 0000                <1>
  2667                              <1> 			; permission denied ! error
  2668 00005A0C E9C3E0FFFF          <1> 	jmp	error
  2669                              <1> ;otty_stc_retn:
  2670                              <1> 	;stc
  2671                              <1> 	;retn
  2672                              <1> ottys_0:
  2673                              <1> 	; 08/01/2022
  2674                              <1> otty_ret: 
  2675                              <1> 	; 13/01/2014
  2676 00005A11 80FE07              <1> 	cmp 	dh, 7
  2677 00005A14 7624                <1> 	jna	short ottys_2
  2678                              <1> 	; 16/11/2015
  2679                              <1> com_port_check:
  2680 00005A16 BE[626B0000]        <1> 	mov	esi, com1p
  2681 00005A1B 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2682 00005A1E 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2683 00005A20 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2684                              <1> ottys_1:
  2685                              <1> 	; 12/11/2015
  2686 00005A21 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2687 00005A24 7714                <1> 	ja	short com_port_ready
  2688                              <1> 	;
  2689                              <1> 	; 09/02/2022
  2690 00005A26 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2691 00005A29 7232                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2692 00005A2B C705[0D6F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2692 00005A33 0000                <1>
  2693                              <1> 			   ; device not ready ! error
  2694                              <1> 	;jmp	short otty_err
  2695 00005A35 E99AE0FFFF          <1> 	jmp	error
  2696                              <1> com_port_ready:
  2697                              <1> ottys_2:
  2698 00005A3A 08C9                <1> 	or	cl, cl  ; cl = lock/owner, ch = open count
  2699 00005A3C 7506                <1> 	jnz	short ottys_3
  2700 00005A3E 8A0D[076F0000]      <1> 	mov	cl, [u.uno]
  2701                              <1> ottys_3:
  2702 00005A44 FEC5                <1> 	inc 	ch
  2703 00005A46 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2704                              <1> 	; 06/12/2013
  2705 00005A49 FEC6                <1> 	inc	dh ; tty number + 1
  2706 00005A4B BB[E86E0000]        <1> 	mov	ebx, u.ttyp
  2707                              <1> 	; 13/01/2014
  2708 00005A50 F6C202              <1> 	test	dl, 2 ; open for read sign
  2709 00005A53 7501                <1> 	jnz	short ottys_4
  2710 00005A55 43                  <1> 	inc	ebx
  2711                              <1> ottys_4:
  2712                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2713 00005A56 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2714                              <1> 	; 09/02/2022
  2715 00005A58 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2716 00005A5A 7401                <1> 	jz	short iclose_retn
  2717                              <1> sret:
  2718                              <1> 	;pop 	ax
  2719 00005A5C 58                  <1> 	pop	eax ; 08/01/2022
  2720                              <1> otty_retn:	; 09/02/2022
  2721                              <1> iclose_retn:	
  2722 00005A5D C3                  <1> 	retn
  2723                              <1> 
  2724                              <1> 	;
  2725                              <1> 	; Original UNIX v1 'otty' routine:
  2726                              <1> 	;	
  2727                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2728                              <1>         ;                 / reader status reg
  2729                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2730                              <1>         ;                 / punch status reg
  2731                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2732                              <1>         ;                          / console tty buffer
  2733                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2734                              <1>         ;            / console tty
  2735                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2736                              <1>         ;             / buffer header
  2737                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2738                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2739                              <1>         ;                 / tty
  2740                              <1>         ;br     sret / ?
  2741                              <1> ;sret:
  2742                              <1> 		;clr *$ps / set processor priority to zero
  2743                              <1> ;	pop	ax
  2744                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2745                              <1> ;3:
  2746                              <1> ;	retn
  2747                              <1>         	;rts r0
  2748                              <1> 	
  2749                              <1> ;ocvt:	; < open tty >
  2750                              <1> 	; 13/01/2014
  2751                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2752                              <1> 	; 24/09/2013 consistency check -> ok
  2753                              <1> 	; 16/09/2013
  2754                              <1> 	; 03/09/2013
  2755                              <1> 	; 27/08/2013
  2756                              <1> 	; 16/08/2013
  2757                              <1> 	; 16/07/2013
  2758                              <1> 	; 27/05/2013
  2759                              <1> 	; 21/05/2013
  2760                              <1> 	;
  2761                              <1> 	; Retro UNIX 8086 v1 modification !
  2762                              <1> 	; 
  2763                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2764                              <1> 	;		(exactly different than this one)
  2765                              <1> 	;	was in 'u9.s' file.
  2766                              <1> 	;
  2767                              <1> 	; 16/07/2013
  2768                              <1> 	; Retro UNIX 8086 v1 modification:
  2769                              <1> 	;  If a tty is open for read or write by
  2770                              <1> 	;     a process (u.uno), only same process can open
  2771                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2772                              <1> 	;
  2773                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2774                              <1> 
  2775                              <1> 	; 16/09/2013
  2776                              <1> 	; sub 	al, 10
  2777                              <1> 	
  2778                              <1> 	; 06/12/2013
  2779                              <1> 	;cmp	al, 7
  2780                              <1>         ;jna     short ottyp
  2781                              <1> 	; 13/01/2014
  2782                              <1> 	;jmp	short ottyp
  2783                              <1> 
  2784                              <1> ;oppt: / open paper tape for reading or writing
  2785                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2786                              <1> ;        tstb   pptiflg / is file already open
  2787                              <1> ;        bne    2f / yes, branch
  2788                              <1> ;1:
  2789                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2790                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2791                              <1> ;               br .+4 / for paper tape input and place in free list
  2792                              <1> ;        br     1b
  2793                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2794                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2795                              <1> ;        br     sret
  2796                              <1> ;2:
  2797                              <1> ;        jmp    error / file already open
  2798                              <1> 
  2799                              <1> iclose:
  2800                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2801                              <1> 	; 19/05/2015
  2802                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2803                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2804                              <1> 	;
  2805                              <1> 	; close file whose i-number is in r1
  2806                              <1> 	; 
  2807                              <1> 	; INPUTS ->
  2808                              <1> 	;    r1 - inode number
  2809                              <1> 	; OUTPUTS ->
  2810                              <1> 	;    file's inode in core	
  2811                              <1> 	;    r1 - inode number (positive)
  2812                              <1> 	;
  2813                              <1> 	; ((AX = R1))
  2814                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2815                              <1> 	;        
  2816                              <1> ;/ close file whose i-number is in r1
  2817 00005A5E B202                <1> 	mov	dl, 2 ; 12/01/2014
  2818 00005A60 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2819                              <1> 		; tst r1 / test i-number
  2820                              <1>         ;jnz	short iclose_2
  2821                              <1> 		; blt 2f / if neg., branch
  2822 00005A63 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2823                              <1> 	; 16/07/2013 
  2824 00005A65 66F7D8              <1> 	neg	ax ; make it positive
  2825                              <1> 	; 12/01/2014
  2826 00005A68 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2827                              <1> iclose_0:
  2828 00005A6A 6683F828            <1> 	cmp	ax, 40
  2829                              <1> 		; cmp r1,$40. / is it a special file
  2830 00005A6E 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2831                              <1> 		; bgt 3b / no, return
  2832                              <1> 	; 12/01/2014
  2833                              <1> 	; DL=2 -> special file was opened for reading
  2834                              <1> 	; DL=1 -> special file was opened for writing
  2835 00005A70 50                  <1> 	push	eax ; 08/01/2022
  2836                              <1> 	;push	ax
  2837                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2838 00005A71 0FB6D8              <1> 	movzx	ebx, al
  2839                              <1> 	; 08/01/2022
  2840 00005A74 C0E302              <1> 	shl	bl, 2
  2841                              <1> 	;shl	bx, 2
  2842                              <1> 		; asl r1
  2843 00005A77 81C3[7B5A0000]      <1> 	add	ebx, iclose_1 - 4
  2844 00005A7D FF23                <1> 	jmp	dword [ebx]
  2845                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2846                              <1> iclose_1 :
  2847 00005A7F [CB5A0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2848 00005A83 [265B0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2849 00005A87 [265B0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2850 00005A8B [265B0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2851 00005A8F [265B0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2852 00005A93 [265B0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2853 00005A97 [265B0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2854 00005A9B [265B0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2855 00005A9F [265B0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2856                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2857                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2858 00005AA3 [DA5A0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2859 00005AA7 [DA5A0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2860 00005AAB [DA5A0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2861 00005AAF [DA5A0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2862 00005AB3 [DA5A0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2863 00005AB7 [DA5A0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2864 00005ABB [DA5A0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2865 00005ABF [DA5A0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2866 00005AC3 [DA5A0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2867 00005AC7 [DA5A0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2868                              <1> 
  2869                              <1> 	; 1:
  2870                              <1> 	;        ctty   / tty
  2871                              <1> 	;        cppt   / ppt
  2872                              <1> 	;        sret   / mem
  2873                              <1> 	;        sret   / rf0
  2874                              <1> 	;        sret   / rk0
  2875                              <1> 	;        sret   / tap0
  2876                              <1> 	;        sret   / tap1
  2877                              <1> 	;        sret   / tap2
  2878                              <1> 	;        sret   / tap3
  2879                              <1> 	;        sret   / tap4
  2880                              <1> 	;        sret   / tap5
  2881                              <1> 	;        sret   / tap6
  2882                              <1> 	;        sret   / tap7
  2883                              <1> 	;        ccvt   / tty0
  2884                              <1> 	;        ccvt   / tty1
  2885                              <1> 	;        ccvt   / tty2
  2886                              <1> 	;        ccvt   / tty3
  2887                              <1> 	;        ccvt   / tty4
  2888                              <1> 	;        ccvt   / tty5
  2889                              <1> 	;        ccvt   / tty6
  2890                              <1> 	;        ccvt   / tty7
  2891                              <1> 	;        error / crd
  2892                              <1> 
  2893                              <1> ;iclose_2: ; 2: / negative i-number
  2894                              <1> 	;neg	ax
  2895                              <1> 		;neg r1 / make it positive
  2896                              <1> 	;cmp	ax, 40
  2897                              <1> 		;cmp r1,$40. / is it a special file?
  2898                              <1>         ;ja	short @b
  2899                              <1> 		;bgt    3b / no. return
  2900                              <1> 	;push	ax
  2901                              <1> 		;mov r1,-(sp)
  2902                              <1> 	;movzx	ebx, al
  2903                              <1> 	;shl	bx, 1
  2904                              <1> 		;asl r1 / yes. compute jump address and transfer
  2905                              <1> 	;add	ebx, iclose_3 - 2
  2906                              <1> 	;jmp	dword [ebx]
  2907                              <1> 		;jmp *1f-2(r1) / figure out 
  2908                              <1> ;iclose_3:
  2909                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2910                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2911                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2912                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2913                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2914                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2915                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2916                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2917                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2918                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2919                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2920                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2921                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2922                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2923                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2924                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2925                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2926                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2927                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2928                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2929                              <1> 	
  2930                              <1> 	;1:
  2931                              <1> 	;      	ctty   / tty
  2932                              <1> 	;       leadr  / ppt
  2933                              <1> 	;       sret   / mem
  2934                              <1> 	;       sret   / rf0
  2935                              <1> 	;       sret   / rk0
  2936                              <1> 	;       sret   / tap0
  2937                              <1> 	;       sret   / tap1
  2938                              <1> 	;       sret   / tap2
  2939                              <1> 	;       sret   / tap3
  2940                              <1> 	;       sret   / tap4
  2941                              <1> 	;       sret   / tap5
  2942                              <1> 	;       sret   / tap6
  2943                              <1> 	;       sret   / tap7
  2944                              <1> 	;       ccvt   / tty0
  2945                              <1> 	;       ccvt   / tty1
  2946                              <1> 	;       ccvt   / tty2
  2947                              <1> 	;       ccvt   / tty3
  2948                              <1> 	;       ccvt   / tty4
  2949                              <1> 	;       ccvt   / tty5
  2950                              <1> 	;       ccvt   / tty6
  2951                              <1> 	;       ccvt   / tty7
  2952                              <1> 	;/      ejec   / lpr
  2953                              <1> 
  2954                              <1> ctty: ; / close console tty
  2955                              <1> 	; 26/02/2022
  2956                              <1> 	; 09/02/2022
  2957                              <1> 	; 06/02/2022
  2958                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2959                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2960                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2961                              <1> 	;
  2962                              <1> 	; Retro UNIX 8086 v1 modification !
  2963                              <1> 	; (DL = 2 -> it is open for reading)
  2964                              <1> 	; (DL = 1 -> it is open for writing)
  2965                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  2966                              <1> 	;
  2967                              <1> 	; 06/12/2013
  2968 00005ACB 0FB61D[076F0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  2969 00005AD2 8A83[176C0000]      <1>         mov     al, [ebx+p.ttyc-1]
  2970                              <1> 	; 13/01/2014
  2971                              <1> 	;jmp	short cttyp
  2972                              <1> 	; 06/02/2022
  2973 00005AD8 EB04                <1> 	jmp	short ctty_0
  2974                              <1> ccvt:
  2975 00005ADA 2C0A                <1> 	sub 	al, 10
  2976                              <1> cttyp:	; (call from sysstty)
  2977                              <1> 	; 08/01/2022
  2978 00005ADC 31DB                <1> 	xor	ebx, ebx
  2979                              <1> ctty_0: ; (ebx < 256)  ; 06/02/2022
  2980                              <1> 	; 08/01/2022
  2981                              <1> 	; 18/05/2015 (32 bit modifications)
  2982                              <1> 	; 16/08/2013 - 26/01/2014
  2983                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  2984                              <1> 	; 08/01/2022
  2985 00005ADE 88C3                <1> 	mov	bl, al
  2986 00005AE0 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  2987                              <1> 	; 26/01/2014
  2988 00005AE2 81C3[446B0000]      <1> 	add 	ebx, ttyl
  2989 00005AE8 88C6                <1> 	mov 	dh, al ; tty number
  2990 00005AEA 668B03              <1> 	mov 	ax, [ebx]
  2991                              <1> 		   ; AL = lock value (0 or process number)
  2992                              <1> 		   ; AH = open count 
  2993 00005AED 20E4                <1> 	and 	ah, ah
  2994 00005AEF 7514                <1> 	jnz	short ctty_ret
  2995                              <1>   	; 09/02/2022
  2996 00005AF1 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  2997 00005AF4 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  2998                              <1> 	; iclose (dl=1 or dl=2)
  2999 00005AF6 C705[0D6F0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  2999 00005AFE 0000                <1>
  3000                              <1> 			; device not open ! error
  3001                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3002 00005B00 E9CFDFFFFF          <1> 	jmp	error
  3003                              <1> 	; 26/01/2014
  3004                              <1> ctty_ret:
  3005 00005B05 FECC                <1> 	dec 	ah ; decrease open count
  3006 00005B07 7502                <1> 	jnz	short ctty_1
  3007 00005B09 30C0                <1> 	xor	al, al ; unlock/free tty
  3008                              <1> ctty_1:
  3009 00005B0B 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3010                              <1> 	;
  3011 00005B0E BB[E86E0000]        <1> 	mov	ebx, u.ttyp
  3012                              <1> 	;test	dl, 1 ; open for write sign
  3013                              <1> 	;jz	short ctty_2
  3014                              <1> 	; 26/02/2022
  3015 00005B13 F6C202              <1> 	test	dl, 2 ; open for read sign
  3016 00005B16 7501                <1> 	jnz	short ctty_2
  3017 00005B18 43                  <1> 	inc	ebx
  3018                              <1> ctty_2:
  3019 00005B19 FEC6                <1> 	inc	dh ; tty number + 1
  3020 00005B1B 3A33                <1> 	cmp	dh, [ebx]
  3021                              <1> 	;jne	short cret
  3022 00005B1D 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3023                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3024 00005B1F C60300              <1> 	mov	byte [ebx], 0
  3025                              <1> ctty_3:
  3026                              <1> 	; 09/02/2022
  3027 00005B22 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3028 00005B24 7401                <1> 	jz	short ctty_4
  3029                              <1> cret:
  3030                              <1> 	;pop	ax
  3031                              <1> 	; 08/01/2022
  3032 00005B26 58                  <1> 	pop	eax
  3033                              <1> ctty_stc_retn:	; 09/02/2022
  3034                              <1> ctty_4:
  3035 00005B27 C3                  <1> 	retn
  3036                              <1> 
  3037                              <1> ;ctty_err: ; 13/01/2014
  3038                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3039                              <1> ;	jnz	error
  3040                              <1> ;	stc
  3041                              <1> ;	retn
  3042                              <1> 
  3043                              <1> 	; Original UNIX v1 'ctty' routine:
  3044                              <1> 	;	
  3045                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3046                              <1> 	;		;/ point r5 to the console tty buffer
  3047                              <1>         ;decb   (r5) / dec number of processes using console tty
  3048                              <1>         ;br     sret / return via sret
  3049                              <1> 
  3050                              <1> ;ccvt:	; < close tty >
  3051                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3052                              <1> 	;
  3053                              <1> 	; Retro UNIX 8086 v1 modification !
  3054                              <1> 	; 
  3055                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3056                              <1> 	;		(exactly different than this one)
  3057                              <1> 	;	was in 'u9.s' file.
  3058                              <1> 	;
  3059                              <1> 	; DL = 2 -> it is open for reading
  3060                              <1> 	; DL = 1 -> it is open for writing
  3061                              <1> 	;
  3062                              <1> 	; 17/09/2013
  3063                              <1> 	;sub 	al, 10
  3064                              <1> 	;cmp	al, 7
  3065                              <1> 	;jna	short cttyp
  3066                              <1> 	; 13/01/2014
  3067                              <1> 	;jmp	short cttyp
  3068                              <1> 
  3069                              <1> ;cppt: / close paper tape
  3070                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3071                              <1> ;1:
  3072                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3073                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3074                              <1> ;                          / and assign to free list
  3075                              <1> ;               br sret
  3076                              <1> ;        br     1b
  3077                              <1> 
  3078                              <1> ;ejec:	
  3079                              <1> ;	jmp	error
  3080                              <1> ;/ejec:
  3081                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3082                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3083                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3084                              <1> ;/       br     sret / return to caller via 'sret'
  2095                                  %include 'u8.s'        ; 11/06/2015
  2096                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS8.INC
  2097                              <1> ; Last Modification: 12/02/2022
  2098                              <1> ; ----------------------------------------------------------------------------
  2099                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2100                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2101                              <1> ;
  2102                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2103                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2104                              <1> ; <Bell Laboratories (17/3/1972)>
  2105                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2106                              <1> ;
  2107                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2108                              <1> ;
  2109                              <1> ; ****************************************************************************
  2110                              <1> 
  2111                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2112                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2113                              <1> ;; Word 1, byte 0 = device id
  2114                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2115                              <1> ;;          bit 9 = write bit
  2116                              <1> ;;	    bit 10 = read bit	  
  2117                              <1> ;;	    bit 12 = waiting to write bit	
  2118                              <1> ;;	    bit 13 = waiting to read bit
  2119                              <1> ;;	    bit 15 = inhibit bit
  2120                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2121                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2122                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2123                              <1> ;;
  2124                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2125                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2126                              <1> ;;
  2127                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2128                              <1> ;; Word 1, Byte 0 = device id
  2129                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2130                              <1> ;;          bit 9 = write bit
  2131                              <1> ;;	    bit 10 = read bit	  
  2132                              <1> ;;	    bit 12 = waiting to write bit	
  2133                              <1> ;;	    bit 13 = waiting to read bit
  2134                              <1> ;;	    bit 15 = inhibit bit
  2135                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2136                              <1> ;;
  2137                              <1> ;; Original UNIX v1 ->
  2138                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2139                              <1> ;; Original UNIX v1 -> 
  2140                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2141                              <1> ;;
  2142                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2143                              <1> ;;
  2144                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2145                              <1> ;;          0 = fd0
  2146                              <1> ;;	    1 = fd1
  2147                              <1> ;;	    2 = hd0
  2148                              <1> ;;	    3 = hd1
  2149                              <1> ;;	    4 = hd2
  2150                              <1> ;;	    5 = hd3
  2151                              <1> 
  2152                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2153                              <1> 
  2154                              <1> 	; 08/02/2022
  2155                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2156                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2157                              <1> 	; 26/04/2013
  2158                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2159                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2160                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2161                              <1> 
  2162                              <1> 	; 08/02/2022
  2163                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2164                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2165                              <1> 	; 26/04/2013
  2166                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2167                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2168                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2169                              <1> 
  2170                              <1> bread: 
  2171                              <1> 	; 08/02/2022
  2172                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2173                              <1> 	; 14/07/2015
  2174                              <1> 	; 10/07/2015
  2175                              <1> 	; 09/06/2015
  2176                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2177                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2178                              <1> 	;	
  2179                              <1> 	; / read a block from a block structured device
  2180                              <1> 	;
  2181                              <1> 	; INPUTS ->
  2182                              <1> 	;    [u.fofp] points to the block number
  2183                              <1> 	;    CX = maximum block number allowed on device
  2184                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2185                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2186                              <1> 	;    [u.count]	number of bytes to read in
  2187                              <1> 	; OUTPUTS ->
  2188                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2189                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2190                              <1> 	;
  2191                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2192                              <1> 	;
  2193                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2194                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2195                              <1> 	;	is increased by 1. For example: If user/program request 
  2196                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2197                              <1> 	;  	the next block number just as 512 byte reading is done.
  2198                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2199                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2200                              <1> 	;       enough to keep byte position/offset of the disk), this
  2201                              <1> 	;	defect will not be corrected, user/program must request
  2202                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2203                              <1> 	;       for achieving correct result. In future version(s), 
  2204                              <1> 	;	this defect will be corrected by using different 
  2205                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2206                              <1> 
  2207                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2208                              <1> 			       ; / (only works on tape)
  2209                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2210                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2211                              <1> ;1:
  2212                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2213                              <1> 			    ; / maximum block # allowed on device
  2214                              <1> 		; jnb short @f
  2215                              <1> 		; bhis	1f / yes, 1f (error)
  2216                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2217                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2218                              <1> 		; mov (sp)+,r1 / return block # to r1
  2219                              <1> 		; inc r1 / bump block # to next consecutive block
  2220                              <1> 		; dec (sp) / "2-1-cold" on stack
  2221                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2222                              <1> ;1:
  2223                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2224                              <1> 	;push	ecx ; **
  2225                              <1> 	; 26/04/2013
  2226                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2227 00005B28 2C03                <1> 	sub	al, 3
  2228                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2229 00005B2A A2[206F0000]        <1> 	mov	[u.brwdev], al
  2230                              <1> 	; 09/06/2015
  2231                              <1> 	;movzx	ebx, al
  2232                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2233                              <1> 	; 12/01/2022 (BugFix)
  2234 00005B2F C0E002              <1> 	shl	al, 2 ; * 4
  2235 00005B32 8B88[1E660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2236                              <1> bread_0:
  2237 00005B38 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2238                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2239                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2240 00005B39 8B1D[C86E0000]      <1> 	mov	ebx, [u.fofp]
  2241 00005B3F 8B03                <1> 	mov	eax, [ebx]
  2242 00005B41 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2243                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2244                              <1> 			       ; / block #
  2245 00005B44 39C8                <1> 	cmp	eax, ecx
  2246                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2247                              <1>        	                     ; / block number allowed
  2248                              <1> 	;jnb	error 	     ; 18/04/2013
  2249                              <1> 		; bhis error10 / yes, error
  2250                              <1> 	; 08/02/2022
  2251                              <1> 	;jb	short bread_1
  2252                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2253                              <1> 	;jmp	error
  2254 00005B46 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2255                              <1> bread_1:
  2256                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2257                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2258                              <1> 	; eAX = Block number (zero based)
  2259                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2260                              <1> preread: ;; call preread
  2261 00005B48 BF[206F0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2262 00005B4D E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2263                              <1> 	;; jc 	error
  2264                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2265                              <1>         ; eAX = Block/Sector number (r1)
  2266                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2267                              <1> 	; 14/03/2013
  2268 00005B52 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2269                              <1>        		; br 1f / branch if block already in a I/O buffer
  2270 00005B54 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2271                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2272 00005B59 E8DA010000          <1> 	call	poke
  2273                              <1>         	; jsr r0,poke / perform the read
  2274                              <1> 	;;jc	error ;2 0/07/2013
  2275                              <1> ; 1:
  2276                              <1>  		; clr *$ps / ps = 0
  2277                              <1>         	; rts r0
  2278                              <1> 	; 08/02/2022
  2279 00005B5E 7305                <1> 	jnc	short bread_2
  2280 00005B60 E937010000          <1> 	jmp	dskrd_err
  2281                              <1> 	;
  2282                              <1> ;; return from preread
  2283                              <1> bread_2:
  2284 00005B65 66810B0040          <1> 	or	word [ebx], 4000h 
  2285                              <1> 		; bis $40000,(r5) 
  2286                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2287                              <1> bread_3: ; 1:
  2288 00005B6A 66F7030024          <1> 	test	word [ebx], 2400h
  2289                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2290 00005B6F 7407                <1> 	jz	short bread_4
  2291                              <1> 		; beq 1f / no
  2292                              <1> 		; cmp cdev,$1 / disk or drum?
  2293                              <1> 		; ble 2f / yes
  2294                              <1> 		; tstb uquant / is the time quantum = 0?
  2295                              <1> 		; bne 2f / no, 2f
  2296                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2297                              <1> 		; jsr r0,sleep; 31. 
  2298                              <1> 			; / put process to sleep in channel 31 (tape)
  2299                              <1> 		; mov (sp)+,r5 / restore r5
  2300                              <1> 		; br 1b / go back
  2301                              <1> ; 2: / drum or disk
  2302                              <1>         ;; mov	cx, [s.wait_]+2 ;; 29/07/2013
  2303 00005B71 E8B5F3FFFF          <1> 	call	idle
  2304                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2305 00005B76 EBF2                <1> 	jmp	short bread_3
  2306                              <1>        		; br 1b
  2307                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2308 00005B78 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2309                              <1> 		; bic $40000,(r5) / clear bit 14
  2310                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2311 00005B7D 83C308              <1> 	add	ebx, 8
  2312                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2313                              <1> 	; 09/06/2015
  2314 00005B80 66833D[1D6F0000]00  <1> 	cmp	word [u.pcount], 0
  2315 00005B88 7705                <1> 	ja	short bread_5
  2316 00005B8A E871F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2317                              <1> bread_5:
  2318                              <1> 	; eBX = system (I/O) buffer address
  2319 00005B8F E870000000          <1> 	call	dioreg
  2320                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2321                              <1> 	; esi = start address of the transfer (in the buffer)
  2322                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2323                              <1> 	; ecx = transfer count (in bytes)
  2324                              <1> 	;
  2325                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2326                              <1> ;   / of users data
  2327 00005B94 F3A4                <1> 	rep	movsb
  2328                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2329                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2330                              <1>        		; bne 1b
  2331 00005B96 59                  <1> 	pop	ecx ; **
  2332 00005B97 833D[DC6E0000]00    <1> 	cmp	dword [u.count], 0
  2333                              <1> 		; tst u.count / done
  2334 00005B9E 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2335                              <1>        		; beq 1f / yes, return
  2336                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2337                              <1>        		; br bread / read some more
  2338                              <1> ; 1:
  2339 00005BA0 58                  <1> 	pop	eax ; ****
  2340                              <1>        		; mov (sp)+,r0
  2341 00005BA1 C3                  <1>         retn		; 09/06/2015
  2342                              <1> 	;jmp	ret_ 
  2343                              <1> 		;jmp ret  / jump to routine that called readi
  2344                              <1> 
  2345                              <1> 	; 08/02/2022
  2346                              <1> brw_oov_err:
  2347 00005BA2 C705[0D6F0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2347 00005BAA 0000                <1>
  2348 00005BAC E923DFFFFF          <1> 	jmp	error
  2349                              <1> 
  2350                              <1> 	; 08/02/2022
  2351                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2352                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2353                              <1> 	; 26/04/2013
  2354                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2355                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2356                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2357                              <1> 
  2358                              <1> 
  2359                              <1> 	; 08/02/2022
  2360                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)				
  2361                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2362                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2363                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2364                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2365                              <1> 
  2366                              <1> bwrite:
  2367                              <1> 	; 08/02/2022
  2368                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2369                              <1> 	; 14/07/2015
  2370                              <1> 	; 10/07/2015
  2371                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2372                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2373                              <1> 	;	
  2374                              <1> 	;; / write on block structured device
  2375                              <1> 	;
  2376                              <1> 	; INPUTS ->
  2377                              <1> 	;    [u.fofp] points to the block number
  2378                              <1> 	;    CX = maximum block number allowed on device
  2379                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2380                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2381                              <1> 	;    [u.count]	number of bytes to user desires to write
  2382                              <1> 	; OUTPUTS ->
  2383                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2384                              <1> 	;
  2385                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2386                              <1> 	;
  2387                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2388                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2389                              <1> 	;	is increased by 1. For example: If user/program request 
  2390                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2391                              <1> 	;  	the next block number just as 512 byte writing is done.
  2392                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2393                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2394                              <1> 	;       enough to keep byte position/offset of the disk), this
  2395                              <1> 	;	defect will not be corrected, user/program must request
  2396                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2397                              <1> 	;       for achieving correct result. In future version(s), 
  2398                              <1> 	;	this defect will be corrected by using different 
  2399                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2400                              <1> 
  2401                              <1>        		; jsr r0,tstdeve / test the device for an error
  2402                              <1> 	;push	ecx ; **
  2403                              <1> 	; 26/04/2013
  2404                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2405 00005BB1 2C03                <1> 	sub	al, 3
  2406                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2407 00005BB3 A2[206F0000]        <1> 	mov	[u.brwdev], al
  2408                              <1> 	; 09/06/2015
  2409                              <1> 	;movzx	ebx, al
  2410                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2411                              <1> 	; 12/01/2022 (BugFix)
  2412 00005BB8 C0E002              <1> 	shl	al, 2 ; * 4
  2413 00005BBB 8B88[1E660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2414                              <1> bwrite_0:
  2415 00005BC1 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2416                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2417                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2418 00005BC2 8B1D[C86E0000]      <1> 	mov	ebx, [u.fofp]
  2419 00005BC8 8B03                <1> 	mov	eax, [ebx]       
  2420 00005BCA C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2421                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2422 00005BCD 39C8                <1> 	cmp	eax, ecx
  2423                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2424                              <1>        	                     ; / block number allowed
  2425                              <1> 	;jnb	error	     ; 18/04/2013
  2426                              <1> 		; bhis error10 / yes, error
  2427                              <1>      	; 08/02/2022
  2428                              <1> 	;jb	short bwrite_1
  2429                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2430                              <1> 	;jmp	error
  2431 00005BCF 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2432                              <1> bwrite_1:
  2433                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2434                              <1> 		; inc *u.fofp / no, increment block number
  2435                              <1> 	; 09/06/2015 - 10/07/2015
  2436 00005BD1 66833D[1D6F0000]00  <1> 	cmp	word [u.pcount], 0
  2437 00005BD9 7705                <1> 	ja	short bwrite_2
  2438 00005BDB E81CF9FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2439                              <1> bwrite_2:
  2440 00005BE0 BF[206F0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2441 00005BE5 E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2442                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2443                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2444 00005BEA E815000000          <1>         call	dioreg
  2445                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2446                              <1> 	; esi = destination address (in the buffer)
  2447                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2448                              <1> 	; ecx = transfer count (in bytes)
  2449                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2450 00005BEF 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2451 00005BF1 F3A4                <1> 	rep	movsb
  2452                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2453                              <1>        		; dec r3 / area to the I/O buffer
  2454                              <1>        		; bne 1b
  2455 00005BF3 E80D010000          <1> 	call	dskwr
  2456                              <1> 		; jsr r0,dskwr / write it out on the device
  2457 00005BF8 59                  <1> 	pop	ecx ; **
  2458 00005BF9 833D[DC6E0000]00    <1>         cmp     dword [u.count], 0
  2459                              <1> 		; tst u.count / done
  2460 00005C00 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2461                              <1> 		; beq 1f / yes, 1f
  2462                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2463                              <1>        		; br bwrite / go back and write next block
  2464                              <1> ; 1:
  2465 00005C02 58                  <1> 	pop	eax ; ****
  2466                              <1>        		; mov (sp)+,r0
  2467 00005C03 C3                  <1> 	retn		; 09/06/2015
  2468                              <1>         ;jmp	ret_ 
  2469                              <1> 		; jmp ret / return to routine that called writei
  2470                              <1> ;error10:
  2471                              <1> ;       jmp     error  ; / see 'error' routine
  2472                              <1> 
  2473                              <1> dioreg:
  2474                              <1> 	; 04/02/2022
  2475                              <1> 	; 14/07/2015
  2476                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2477                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2478                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2479                              <1> 	;	
  2480                              <1> 	; bookkeeping on block transfers of data
  2481                              <1> 	;
  2482                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2483                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2484                              <1> 	; 10/07/2015
  2485                              <1> 	; * returns byte offset from beginning of current sector buffer
  2486                              <1> 	; (beginning of data) in ESI
  2487                              <1> 	;
  2488 00005C04 8B0D[DC6E0000]      <1> 	mov	ecx, [u.count]
  2489                              <1> 		; mov u.count,r3 / move char count to r3
  2490                              <1> 	; 04/02/2022
  2491 00005C0A 31D2                <1> 	xor	edx, edx
  2492 00005C0C B602                <1> 	mov	dh, 2
  2493                              <1> 	; edx = 512
  2494 00005C0E 39D1                <1> 	cmp	ecx, edx ; 512
  2495                              <1> 	;cmp 	ecx, 512
  2496                              <1> 		; cmp r3,$512. / more than 512. char?
  2497 00005C10 7602                <1> 	jna	short dioreg_0
  2498                              <1> 		; blos 1f / no, branch
  2499 00005C12 89D1                <1> 	mov	ecx, edx ; 512
  2500                              <1> 	;mov	ecx, 512
  2501                              <1> 		; mov $512.,r3 / yes, just take 512.
  2502                              <1> dioreg_0:
  2503                              <1> 	; 09/06/2015
  2504 00005C14 663B0D[1D6F0000]    <1> 	cmp	cx, [u.pcount]
  2505 00005C1B 7607                <1> 	jna	short dioreg_1
  2506 00005C1D 668B0D[1D6F0000]    <1> 	mov	cx, [u.pcount]
  2507                              <1> dioreg_1:
  2508                              <1> ; 1:
  2509 00005C24 8B15[D86E0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2510                              <1> 	        ; mov u.base,r2 / put users base in r2
  2511 00005C2A 010D[E06E0000]      <1> 	add	[u.nread], ecx
  2512                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2513 00005C30 290D[DC6E0000]      <1> 	sub	[u.count], ecx
  2514                              <1> 		; sub r3,u.count / update count
  2515 00005C36 010D[D86E0000]      <1> 	add	[u.base], ecx
  2516                              <1> 		; add r3,u.base / update base
  2517                              <1> 	; 10/07/2015
  2518                              <1> 	; Retro UNIX 386 v1 - modification !
  2519                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2520                              <1> 	; (It will point to next byte position instead of next block no.)
  2521 00005C3C 8B35[C86E0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2522 00005C42 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2523 00005C44 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2524 00005C46 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2525 00005C4B 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2526 00005C4D 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2527                              <1> 	; 09/06/2015 - 10/07/2015
  2528 00005C4F 66290D[1D6F0000]    <1> 	sub	[u.pcount], cx
  2529 00005C56 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2530 00005C5C 8B3D[196F0000]      <1> 	mov	edi, [u.pbase]
  2531 00005C62 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2532 00005C68 01D7                <1> 	add	edi, edx
  2533 00005C6A 893D[196F0000]      <1> 	mov	[u.pbase], edi
  2534 00005C70 010D[196F0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2535 00005C76 C3                  <1> 	retn
  2536                              <1> 		; rts r0 / return
  2537                              <1> 
  2538                              <1> dskrd:
  2539                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2540                              <1> 	; 18/08/2015
  2541                              <1> 	; 02/07/2015
  2542                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2543                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2544                              <1> 	;
  2545                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2546                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2547                              <1> 	; (number specified in r1) in the acquired buffer.)
  2548                              <1> 	; If the device is busy at the time dskrd is called,	
  2549                              <1> 	; dskrd calls idle.
  2550                              <1> 	; 
  2551                              <1> 	; INPUTS ->
  2552                              <1> 	;    r1 - block number
  2553                              <1> 	;    cdev - current device number 
  2554                              <1> 	; OUTPUTS ->
  2555                              <1> 	;    r5 - points to first data word in I/O buffer
  2556                              <1> 	;
  2557                              <1> 	; ((AX = R1)) input/output
  2558                              <1> 	; ((BX = R5)) output 
  2559                              <1> 	;
  2560                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2561                              <1> 	;
  2562 00005C77 E851010000          <1> 	call 	bufaloc
  2563                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2564                              <1> 			       ; / get a free I/O buffer
  2565                              <1> 	;;jc	error ; 20/07/2013
  2566 00005C7C 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2567                              <1>        		; br 1f / branch if block already in a I/O buffer
  2568                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2569 00005C7E 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2570                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2571                              <1> 		               ; / I/O queue entry for buffer
  2572 00005C83 E8B0000000          <1> 	call	poke
  2573                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2574                              <1> 			    ; /	bit 10=1 says read
  2575                              <1> 	; 09/06/2015
  2576                              <1> 	;jnc	short dskrd_1
  2577                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2578                              <1> 	;jmp	error
  2579                              <1> 	; 08/02/2022
  2580 00005C88 7212                <1> 	jc	short dskrd_3
  2581                              <1> dskrd_1: ; 1:
  2582                              <1>        		;clr *$ps
  2583 00005C8A 66F7030024          <1>        	test	word [ebx], 2400h
  2584                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2585                              <1> 				; / jump to idle
  2586 00005C8F 7407                <1>        	jz	short dskrd_2
  2587                              <1> 		; beq 1f
  2588                              <1>         ;;mov   ecx, [s.wait_]
  2589 00005C91 E895F2FFFF          <1>        	call	idle
  2590                              <1> 		; jsr r0,idle; s.wait+2
  2591 00005C96 EBF2                <1> 	jmp 	short dskrd_1
  2592                              <1>        		; br 1b
  2593                              <1> dskrd_2: ; 1:
  2594 00005C98 83C308              <1>         add	ebx, 8
  2595                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2596                              <1> 			  ; / just read in
  2597 00005C9B C3                  <1>        	retn
  2598                              <1> 		; rts r0
  2599                              <1> dskrd_err: 
  2600                              <1> 	; 08/02/2022
  2601                              <1> 	; (jump from 'bread' error)	
  2602                              <1> dskrd_3:	
  2603                              <1> 	; 08/02/2022
  2604 00005C9C 803D[206F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2605 00005CA3 7509                <1> 	jne	short dskrd_4 ; no
  2606                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2607 00005CA5 C605[206F0000]00    <1> 	mov	byte [u.brwdev], 0
  2608 00005CAC EB0A                <1> 	jmp	short dskrd_5
  2609                              <1> dskrd_4:
  2610 00005CAE C705[0D6F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2610 00005CB6 0000                <1>
  2611                              <1> dskrd_5:
  2612 00005CB8 E917DEFFFF          <1> 	jmp	error
  2613                              <1> 
  2614                              <1> bwslot:
  2615                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2616                              <1> 	; 10/07/2015
  2617                              <1> 	;	If the block/sector is not placed in a buffer
  2618                              <1> 	;	before 'wslot', it must be read before
  2619                              <1> 	;	it is written! (Otherwise transfer counts less
  2620                              <1> 	;	than 512 bytes will be able to destroy existing 
  2621                              <1> 	;	data on disk.)
  2622                              <1> 	;
  2623                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2624                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2625                              <1> 	; Retro UNIX 8086 v1 modification !
  2626                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2627                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2628                              <1> 	;	-> eAX = block number
  2629                              <1> 	;
  2630 00005CBD E818010000          <1> 	call	bufaloc_0
  2631 00005CC2 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2632                              <1> 	; 12/01/2022
  2633                              <1> 	; ebx = buffer header address
  2634                              <1> bwslot_0:
  2635                              <1> 	; 10/07/2015
  2636 00005CC4 8B35[C86E0000]      <1> 	mov	esi, [u.fofp]
  2637 00005CCA 8B06                <1> 	mov	eax, [esi]
  2638 00005CCC 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2639 00005CD1 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2640                              <1> 		       ; recent disk data must be placed in the buffer
  2641 00005CD3 813D[DC6E0000]0002- <1> 	cmp	dword [u.count], 512
  2641 00005CDB 0000                <1>
  2642 00005CDD 730F                <1> 	jnb	short wslot_0	
  2643                              <1> bwslot_1:
  2644 00005CDF E89AFFFFFF          <1> 	call	dskrd_0
  2645                              <1> 	; 12/01/2022
  2646                              <1> 	; ebx = buffer data address = buffer header address + 8
  2647 00005CE4 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2648 00005CE7 EB05                <1> 	jmp 	short wslot_0
  2649                              <1> 
  2650                              <1> wslot:
  2651                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2652                              <1> 	; 		(32 bit modifications)
  2653                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2654                              <1> 	;
  2655                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2656                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2657                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2658                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2659                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2660                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2661                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2662                              <1> 	;
  2663                              <1> 	; INPUTS ->
  2664                              <1>  	;    r1 - block number
  2665                              <1> 	;    cdev - current (block/disk) device number
  2666                              <1>  	;
  2667                              <1> 	; OUTPUTS ->
  2668                              <1> 	;    bufp - bits 9 and 15 are set, 
  2669                              <1> 	;           the remainder of the word left unchanged
  2670                              <1> 	;    r5 - points to first data word in I/O buffer
  2671                              <1> 	;
  2672                              <1> 	; ((AX = R1)) input/output
  2673                              <1> 	; ((BX = R5)) output 
  2674                              <1> 	;
  2675                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2676                              <1> 
  2677 00005CE9 E8DF000000          <1> 	call	bufaloc
  2678                              <1> 	; 10/07/2015
  2679                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2680                              <1>         	; br 1f / word in buffer in r5
  2681                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2682                              <1>         ; eAX = Block/Sector number (r1)
  2683                              <1> wslot_0: ;1:
  2684 00005CEE 66F7030024          <1>      	test	word [ebx], 2400h
  2685                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2686                              <1> 				; / of I/O queue entry
  2687 00005CF3 7407                <1> 	jz	short wslot_1
  2688                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2689                              <1> 		     ; / or not waiting to read)
  2690                              <1> 
  2691                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2692 00005CF5 E831F2FFFF          <1> 	call	idle
  2693                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2694                              <1>        	                     ; / idle
  2695 00005CFA EBF2                <1> 	jmp	short wslot_0
  2696                              <1> 		; br 1b / till finished
  2697                              <1> wslot_1: ;1:
  2698 00005CFC 66810B0082          <1>         or      word [ebx], 8200h
  2699                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2700                              <1>                             	 ; / (write, inhibit bits)
  2701                              <1>        		; clr     *$ps / clear processor status
  2702 00005D01 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2703                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2704                              <1> 			  ; / for this block
  2705                              <1> dskwr_1:	; 08/02/2022
  2706 00005D04 C3                  <1>        	retn
  2707                              <1> 		; rts r0
  2708                              <1> dskwr:
  2709                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2710                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2711                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2712                              <1> 	;
  2713                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2714                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2715                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2716                              <1> 	; previously has supplied all the information required in the
  2717                              <1> 	; I/O queue entry.
  2718                              <1> 	;
  2719                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2720                              <1> 	;
  2721                              <1> 	;
  2722 00005D05 8B1D[7C6E0000]      <1> 	mov	ebx, [bufp]
  2723 00005D0B 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2724                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2725                              <1>                                   ; / bottom of queue
  2726 00005D10 E823000000          <1> 	call	poke
  2727                              <1> 	; 09/06/2015
  2728 00005D15 73ED                <1> 	jnc	short dskwr_1
  2729                              <1> 	; 08/02/2022
  2730 00005D17 803D[206F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2731 00005D1E 7509                <1> 	jne	short dskwr_0 ; no
  2732                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2733 00005D20 C605[206F0000]00    <1> 	mov	byte [u.brwdev], 0
  2734 00005D27 EB0A                <1> 	jmp	short dskwr_2
  2735                              <1> dskwr_0:
  2736 00005D29 C705[0D6F0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2736 00005D31 0000                <1>
  2737                              <1> dskwr_2:
  2738 00005D33 E99CDDFFFF          <1> 	jmp	error
  2739                              <1> ;dskwr_1:
  2740                              <1> ;	retn
  2741                              <1> 
  2742                              <1> ;ppoke:
  2743                              <1>        		; mov $340,*$ps
  2744                              <1>        		; jsr r0,poke
  2745                              <1>        		; clr *$ps
  2746                              <1> 		; rts r0
  2747                              <1> poke:
  2748                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2749                              <1> 	; 24/10/2015
  2750                              <1> 	; 20/08/2015
  2751                              <1> 	; 18/08/2015
  2752                              <1> 	; 02/07/2015
  2753                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2754                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2755                              <1> 	;
  2756                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2757                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2758                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2759                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2760                              <1> 	;
  2761                              <1> 	; Basic I/O functions for all block structured devices
  2762                              <1> 	;
  2763                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2764                              <1> 	;
  2765                              <1> 	; 20/07/2013 modifications
  2766                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2767                              <1> 	; INPUTS -> 
  2768                              <1> 	;        (EBX = buffer header address)
  2769                              <1> 	; OUTPUTS ->
  2770                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2771                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2772                              <1> 	;		(drive not ready or r/w error!)
  2773                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2774                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2775                              <1> 	;        (also it indicates invalid buffer data)
  2776                              <1> 	;
  2777 00005D38 53                  <1> 	push	ebx
  2778                              <1>        		; mov r1,-(sp)
  2779                              <1>        		; mov r2,-(sp)
  2780                              <1>        		; mov r3,-(sp)
  2781 00005D39 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2782                              <1> 	;
  2783                              <1> 	; 09/06/2015
  2784                              <1> 	; (permit read/write after a disk  R/W error)
  2785 00005D3A 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2786 00005D3C B001                <1> 	mov	al, 1
  2787 00005D3E D2E0                <1> 	shl	al, cl
  2788 00005D40 8405[A26E0000]      <1> 	test 	al, [active] ; busy ? (error)
  2789 00005D46 7408                <1> 	jz	short poke_0
  2790 00005D48 F6D0                <1> 	not	al
  2791 00005D4A 2005[A26E0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2792                              <1> poke_0:
  2793 00005D50 BE[9C6E0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2794                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2795                              <1> 					 ; / I/O queue pointer
  2796                              <1> poke_1: ; 1:
  2797 00005D55 83EE04              <1>         sub	esi, 4
  2798 00005D58 8B1E                <1> 	mov	ebx, [esi]
  2799                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2800 00005D5A 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2801 00005D5D F6C406              <1>        	test	ah, 06h
  2802                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2803                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2804                              <1> 			       ; / queue entry
  2805 00005D60 745C                <1>         jz      short poke_5
  2806                              <1> 		; beq 2f / branch to 2f if both are clear
  2807                              <1> 	; 31/07/2013
  2808                              <1> 	;test	ah, 0B0h ; (*)
  2809                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2810                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2811                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2812                              <1> 		; bne 2f / branch if any are set
  2813                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2814                              <1>     		; movb (r1),r3 / get device id
  2815 00005D62 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2816                              <1> 	;mov	edi, ecx ; 26/04/2013
  2817 00005D65 31C0                <1> 	xor 	eax, eax ; 0
  2818                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2819                              <1> 		; tstb deverr(r3) / test for errors on this device
  2820                              <1>        	;jna	short poke_2 
  2821                              <1> 		; beq 3f / branch if no errors
  2822                              <1> 	; 02/07/2015
  2823                              <1> 	;dec	eax
  2824                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2825                              <1>        		; mov $-1,2(r1) / destroy associativity
  2826                              <1> 	;shr	eax, 24
  2827                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2828                              <1> 		; clrb 1(r1) / do not do I/O
  2829                              <1> 	;jmp	short poke_5
  2830                              <1>         ;       ; br 2f
  2831                              <1>                 ; rts r0
  2832                              <1> poke_2: ; 3:
  2833                              <1> 	; 02/07/2015
  2834 00005D67 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2835 00005D69 7453                <1> 	jz	short poke_5
  2836 00005D6B FEC0                <1> 	inc	al ; mov ax, 1
  2837 00005D6D FEC9                <1> 	dec	cl
  2838 00005D6F 7402                <1> 	jz	short poke_3
  2839                              <1> 	; 26/04/2013 Modification
  2840                              <1> 	;inc	al ; mov ax, 1
  2841                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2842                              <1> 	;jz	short poke_3 ; cl = 0
  2843 00005D71 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2844                              <1> poke_3:
  2845                              <1> 	;test	[active], ax
  2846 00005D73 8405[A26E0000]      <1> 	test	[active], al
  2847                              <1> 		; bit $2,active / test disk busy bit
  2848 00005D79 7543                <1> 	jnz     short poke_5
  2849                              <1> 		; bne 2f / branch if bit is set
  2850                              <1> 	;or	[active], ax
  2851 00005D7B 0805[A26E0000]      <1> 	or	[active], al
  2852                              <1> 		; bis $2,active / set disk busy bit
  2853                              <1> 	;push	ax
  2854                              <1> 	; 24/12/2021
  2855 00005D81 50                  <1> 	push	eax
  2856 00005D82 E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2857                              <1> 	;mov    [edi+drv.error], ah
  2858                              <1> 	; 24/12/2021
  2859 00005D87 58                  <1> 	pop	eax
  2860                              <1> 	;pop	ax
  2861 00005D88 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2862                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2863                              <1> 	;jna	short poke_4
  2864                              <1> 		; tstb deverr(r3) / test for errors on this device
  2865                              <1>        		; beq 3f / branch if no errors
  2866                              <1> 	; 02/07/2015 (32 bit modification)
  2867                              <1> 	; 20/07/2013
  2868 00005D8A C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2869                              <1>        		; mov $-1,2(r1) / destroy associativity
  2870 00005D91 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2871                              <1> 		; clrb 1(r1) / do not do I/O
  2872 00005D96 EB26                <1> 	jmp     short poke_5
  2873                              <1> poke_4:	; 20/07/2013
  2874                              <1> 	; 17/07/2013
  2875 00005D98 F6D0                <1> 	not 	al 
  2876 00005D9A 2005[A26E0000]      <1> 	and	[active], al ; reset, not busy
  2877                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2878                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2879 00005DA0 668B03              <1> 	mov	ax, [ebx]
  2880                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2881 00005DA3 66250006            <1>         and	ax, 600h
  2882                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2883 00005DA7 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2884                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2885 00005DAC C0E403              <1> 	shl	ah, 3
  2886                              <1>        		; rol r3
  2887                              <1>                 ; rol r3
  2888                              <1>                 ; rol r3	
  2889 00005DAF 660903              <1> 	or	[ebx], ax
  2890                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2891                              <1> 			   ; bits 12 and 13
  2892 00005DB2 E874F1FFFF          <1> 	call	idle ; 18/01/2014
  2893                              <1> 	;; sti
  2894                              <1> 	;hlt 	; wait for a hardware interrupt
  2895                              <1> 	;; cli
  2896                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2897                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2898                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2899                              <1> 	; method, this procedure will wait for a time according to
  2900                              <1> 	; multi tasking and time sharing concept.
  2901                              <1> 	;
  2902                              <1> 	; 24/10/2015
  2903                              <1> 	;not	ax 
  2904 00005DB7 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2905 00005DBB 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2906                              <1> poke_5: ;2:
  2907 00005DBE 81FE[7C6E0000]      <1>         cmp     esi, bufp
  2908                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2909                              <1>                             ; / has been scanned
  2910 00005DC4 778F                <1> 	ja      short poke_1
  2911                              <1>                ; bhi 1b
  2912                              <1> 	; 24/03/2013
  2913                              <1>        		; mov (sp)+,r3
  2914                              <1>        		; mov (sp)+,r2
  2915                              <1>        		; mov (sp)+,r1
  2916 00005DC6 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2917 00005DC7 5B                  <1> 	pop 	ebx
  2918                              <1> 	; 02/07/2015 (32 bit modification)
  2919                              <1> 	; 20/07/2013
  2920                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2921 00005DC8 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2922                              <1> 	;	
  2923                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2924                              <1> 	; or written successfully; even if an error occurs while
  2925                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2926                              <1> 	;
  2927                              <1> 	; 09/06/2015
  2928 00005DCB F5                  <1> 	cmc
  2929 00005DCC C3                  <1> 	retn
  2930                              <1>                 ; rts r0
  2931                              <1> 
  2932                              <1> bufaloc:
  2933                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2934                              <1> 	; 20/08/2015
  2935                              <1> 	; 19/08/2015
  2936                              <1> 	; 02/07/2015
  2937                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2938                              <1> 	;	     (32 bit modifications)	
  2939                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2940                              <1> 	;
  2941                              <1> 	; bufaloc - Block device I/O buffer allocation
  2942                              <1> 	; 
  2943                              <1> 	; INPUTS ->
  2944                              <1> 	;    r1 - block number
  2945                              <1> 	;    cdev - current (block/disk) device number
  2946                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2947                              <1> 	; OUTPUTS ->
  2948                              <1> 	;    r5 - pointer to buffer allocated
  2949                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2950                              <1> 	;
  2951                              <1> 	; ((AX = R1)) input/output
  2952                              <1> 	; ((BX = R5)) output
  2953                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2954                              <1> 	;    zf=1 -> block already in a I/O buffer
  2955                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2956                              <1> 	;    ((DL = Device ID))
  2957                              <1> 	;    (((DH = 0 or 1)))
  2958                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2959                              <1> 	;    ((CX and DH will not be used after return)))
  2960                              <1> 
  2961                              <1> 	;;push 	esi ; ***
  2962                              <1> 		; mov r2,-(sp) / save r2 on stack
  2963                              <1>        		; mov $340,*$ps / set processor priority to 7
  2964                              <1> 	; 20/07/2013
  2965                              <1> 	; 26/04/2013
  2966                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2967                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  2968                              <1> 	;add	edi, ebx
  2969                              <1> 	; 09/01/2022
  2970 00005DCD 0FB63D[9F6E0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2971 00005DD4 81C7[A06E0000]      <1> 	add	edi, rdev
  2972                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2973                              <1> 			;; eDI points to device id.
  2974 00005DDA 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2975                              <1> 	; 11/06/2015
  2976 00005DDD 80BB[3A660000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2977 00005DE4 720F                <1> 	jb	short bufaloc_9
  2978 00005DE6 C705[0D6F0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2978 00005DEE 0000                <1>
  2979 00005DF0 E9DFDCFFFF          <1> 	jmp	error
  2980                              <1> bufaloc_9:
  2981 00005DF5 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2982                              <1> bufaloc_10: ; 02/07/2015
  2983 00005DF7 31ED                <1> 	xor 	ebp, ebp ; 0
  2984 00005DF9 55                  <1> 	push	ebp ; 0
  2985 00005DFA 89E5                <1>         mov     ebp, esp	
  2986                              <1> 	;
  2987                              <1> bufaloc_1: ;1:
  2988                              <1> 		; clr -(sp) / vacant buffer
  2989 00005DFC BE[7C6E0000]        <1>         mov 	esi, bufp
  2990                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2991                              <1> 			     ; / entrys in buffer area
  2992                              <1> bufaloc_2: ;2:
  2993 00005E01 8B1E                <1> 	mov	ebx, [esi]
  2994                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2995                              <1> 			    ; queue entry into r5
  2996 00005E03 66F70300F6          <1> 	test	word [ebx], 0F600h
  2997                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2998 00005E08 7503                <1>         jnz	short bufaloc_3
  2999                              <1> 		; bne 3f / branch when 
  3000                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3001                              <1>                        ; / (i.e., buffer busy)
  3002 00005E0A 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  3003                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  3004                              <1> 			; / found points to word 2 of I/O queue entry)
  3005                              <1> bufaloc_3: ;3:
  3006                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3007                              <1> 	;
  3008 00005E0D 3813                <1> 	cmp	[ebx], dl	
  3009                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3010                              <1> 			       ; / as current device
  3011 00005E0F 7508                <1> 	jne	short bufaloc_4
  3012                              <1>        		; bne 3f
  3013 00005E11 394304              <1> 	cmp	[ebx+4], eax
  3014                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3015                              <1> 			     ; / same as current block number
  3016 00005E14 7503                <1>        	jne	short bufaloc_4
  3017                              <1> 		; bne 3f
  3018                              <1> 	;add	esp, 4
  3019 00005E16 59                  <1> 	pop	ecx
  3020                              <1>        		; tst (sp)+ / bump stack pointer
  3021 00005E17 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3022                              <1> 				; jump to bufaloc_6 in original Unix v1
  3023                              <1>        		; br 1f / use this buffer
  3024                              <1> bufaloc_4: ;3:
  3025 00005E19 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3026                              <1> 	;
  3027 00005E1C 81FE[946E0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3028                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3029 00005E22 72DD                <1> 	jb	short bufaloc_2
  3030                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3031                              <1>                        ; / buffers not checked)
  3032 00005E24 5E                  <1>         pop	esi
  3033                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3034                              <1> 			     ; / to last free block
  3035 00005E25 09F6                <1>        	or	esi, esi 
  3036 00005E27 7507                <1> 	jnz	short bufaloc_5
  3037                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3038                              <1> 	        ; / if a free buffer is found branch to 2f
  3039                              <1>         ;; mov  ecx, [s.wait_]
  3040 00005E29 E8FDF0FFFF          <1> 	call	idle
  3041                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  3042 00005E2E EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3043                              <1>        		; br 1b
  3044                              <1> bufaloc_5: ;2:
  3045                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3046 00005E30 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3047                              <1> bufaloc_6: ;1:
  3048 00005E32 8B1E                <1>         mov    	ebx, [esi] 
  3049                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3050                              <1> 			     ; / entry in r5
  3051                              <1> 	;; 26/04/2013
  3052                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3053 00005E34 8813                <1> 	mov 	[ebx], dl
  3054                              <1> 		; movb cdev,(r5) / put current device number 
  3055                              <1> 				 ; / in I/O queue entry
  3056 00005E36 894304              <1> 	mov 	[ebx+4], eax
  3057                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3058                              <1> 			     ; / of I/O queue entry
  3059                              <1> bufaloc_7: ;1:
  3060 00005E39 81FE[7C6E0000]      <1>         cmp	esi, bufp
  3061                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3062                              <1> 			     ; / and put latest assigned
  3063 00005E3F 760A                <1> 	jna	short bufaloc_8	
  3064                              <1>        		; blos 1f / buffer on the top 
  3065                              <1> 			; / (this makes if the lowest priority)
  3066 00005E41 83EE04              <1> 	sub	esi, 4
  3067 00005E44 8B0E                <1> 	mov	ecx, [esi]
  3068 00005E46 894E04              <1> 	mov	[esi+4], ecx
  3069                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3070 00005E49 EBEE                <1> 	jmp 	short bufaloc_7        
  3071                              <1> 		; br 1b
  3072                              <1> bufaloc_8: ;1:
  3073 00005E4B 891E                <1>         mov	[esi], ebx
  3074                              <1> 		; mov r5,(r2)
  3075                              <1> 	;;pop	esi ; ***
  3076                              <1>        		; mov (sp)+,r2 / restore r2
  3077 00005E4D 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3078                              <1> 		; Retro UNIX 8086 v1 modification
  3079                              <1> 		; zf=1 --> block already is in an I/O buffer
  3080                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3081 00005E4F C3                  <1> 	retn
  3082                              <1> 		; rts r0
  3083                              <1> 
  3084                              <1> diskio:
  3085                              <1> 	; 12/02/2022
  3086                              <1> 	; 10/02/2022
  3087                              <1> 	; 08/02/2022
  3088                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2)
  3089                              <1> 	; 10/07/2015
  3090                              <1> 	; 02/07/2015
  3091                              <1> 	; 16/06/2015
  3092                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3093                              <1> 	;	     (80386 protected mode modifications)	
  3094                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3095                              <1> 	;
  3096                              <1> 	; Retro UNIX 8086 v1 feature only !
  3097                              <1> 	;
  3098                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3099                              <1> 	; 04/07/2009 - 20/07/2011
  3100                              <1> 	;
  3101                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3102                              <1> 	;
  3103                              <1>         ; INPUTS ->
  3104                              <1> 	; 	   eBX = System I/O Buffer header address
  3105                              <1> 	;
  3106                              <1>         ; OUTPUTS -> cf=0 --> done 
  3107                              <1> 	; 	     cf=1 --> error code in AH
  3108                              <1> 	;	     ; 08/02/2022
  3109                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3110                              <1> 	;		error code in [u.error]
  3111                              <1> 	;		
  3112                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3113                              <1> 	
  3114                              <1> ;rw_disk_sector:
  3115                              <1> 	; 12/02/2022
  3116                              <1> 	; 10/02/2022
  3117                              <1> 	; 08/02/2022
  3118                              <1> 	; 10/07/2015
  3119                              <1> 	; 02/07/2015
  3120                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3121                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3122                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3123                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3124                              <1> 	;
  3125                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3126 00005E50 B602                <1> 	mov	dh, 2
  3127 00005E52 668B03              <1> 	mov	ax, [ebx] 
  3128                              <1> 	;
  3129 00005E55 56                  <1> 	push	esi ; ****
  3130 00005E56 53                  <1> 	push	ebx ; ***
  3131                              <1> 	;
  3132 00005E57 0FB6C8              <1> 	movzx	ecx, al
  3133 00005E5A 89CE                <1> 	mov	esi, ecx
  3134                              <1> 	;
  3135 00005E5C 38F1                <1> 	cmp	cl, dh ; 2
  3136 00005E5E 7202                <1> 	jb	short rwdsk0
  3137 00005E60 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3138                              <1> rwdsk0:
  3139 00005E62 A2[EB650000]        <1> 	mov	[drv], al
  3140 00005E67 81C6[3A660000]      <1> 	add	esi, drv.status
  3141                              <1> 	; 11/06/2015
  3142 00005E6D 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3143 00005E70 7204                <1> 	jb      short rwdsk1
  3144                              <1> 	; 'drive not ready' error
  3145                              <1> 	; 10/02/2022
  3146                              <1> 	; 08/02/2022
  3147                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3148                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3149                              <1> 	;;jmp	error
  3150                              <1> 	;stc	; cf = 1
  3151                              <1> 	;retn
  3152                              <1> 	; 10/02/2022
  3153 00005E72 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3154 00005E74 EB20                <1> 	jmp	short rwdsk_err1
  3155                              <1> rwdsk1:
  3156 00005E76 F6C402              <1> 	test	ah, 2
  3157                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3158                              <1> 			 ; write bit
  3159 00005E79 7402                <1> 	jz	short rwdsk2
  3160                              <1> 	;test	ah, 4
  3161                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3162                              <1> 	;		 ; read bit
  3163                              <1> 	;jz	short diskio_ret
  3164 00005E7B FEC6                <1> 	inc	dh ; 03h = write
  3165                              <1> rwdsk2:
  3166 00005E7D 88C2                <1> 	mov	dl, al
  3167 00005E7F 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3168 00005E82 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3169 00005E84 C0E102              <1> 	shl	cl, 2
  3170 00005E87 81C1[1E660000]      <1> 	add	ecx, drv.size ; disk size
  3171 00005E8D 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3172 00005E8F 7214                <1> 	jb      short rwdsk3
  3173                              <1>  	; 'out of volume' error
  3174                              <1> 	; 10/02/2022
  3175                              <1> 	; 08/02/2022
  3176                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3177                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3178                              <1> 	;;jmp	error
  3179                              <1> 	;stc	; cf = 1
  3180                              <1> 	;retn
  3181                              <1> 	; 10/02/2022
  3182 00005E91 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3183                              <1> rwdsk_err1:
  3184 00005E96 C605[206F0000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3185 00005E9D 890D[0D6F0000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3186 00005EA3 EB30                <1> 	jmp	short rwdsk_err2
  3187                              <1> rwdsk3:
  3188                              <1> 	; 11/06/2015
  3189 00005EA5 83C304              <1> 	add	ebx, 4 ; buffer address
  3190 00005EA8 C605[3E6F0000]04    <1> 	mov	byte [retry_count], 4
  3191 00005EAF F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3192 00005EB2 7432                <1>         jz      short rwdsk_chs
  3193                              <1> rwdsk_lba:
  3194                              <1> 	; LBA read/write (with private LBA function) 
  3195                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3196 00005EB4 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3197 00005EB7 89C1                <1> 	mov	ecx, eax ; sector number
  3198                              <1> 	; ebx = buffer (data) address
  3199                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3200                              <1> rwdsk_lba_retry:
  3201                              <1> 	;mov	dl, [drv]
  3202                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3203 00005EB9 B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3204 00005EBB 00F4                <1> 	add	ah, dh		
  3205 00005EBD B001                <1> 	mov	al, 1
  3206                              <1> 	;int	13h
  3207 00005EBF E8D9C6FFFF          <1> 	call	int13h
  3208 00005EC4 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3209 00005EC6 730E                <1> 	jnc	short rwdsk_lba_ok
  3210 00005EC8 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3211 00005ECB 7408                <1>         je      short rwdsk_lba_fails
  3212 00005ECD FE0D[3E6F0000]      <1> 	dec	byte [retry_count]
  3213 00005ED3 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3214                              <1> rwdsk_err2:	; 10/02/2022
  3215                              <1> rwdsk_lba_fails:
  3216 00005ED5 F9                  <1> 	stc
  3217                              <1> rwdsk_lba_ok:
  3218 00005ED6 5B                  <1> 	pop	ebx ; ***
  3219 00005ED7 5E                  <1> 	pop	esi ; ****
  3220 00005ED8 C3                  <1> 	retn
  3221                              <1> rwdsk_lba_reset:
  3222 00005ED9 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3223                              <1> 	;int	13h
  3224 00005EDB E8BDC6FFFF          <1>         call	int13h
  3225 00005EE0 73D7                <1> 	jnc     short rwdsk_lba_retry
  3226 00005EE2 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3227 00005EE4 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3228                              <1> 	;
  3229                              <1> 	; CHS read (convert LBA address to CHS values)	
  3230                              <1> rwdsk_chs:
  3231                              <1> 	; 10/07/2015
  3232 00005EE6 81EE[3A660000]      <1> 	sub	esi, drv.status
  3233 00005EEC 89F1                <1> 	mov	ecx, esi
  3234 00005EEE 81C6[41660000]      <1> 	add 	esi, drv.error
  3235                              <1> 	; 02/07/2015
  3236                              <1> 	; 16/06/2015
  3237                              <1>  	; 11/06/2015 
  3238 00005EF4 53                  <1> 	push	ebx ; ** ; buffer
  3239 00005EF5 D1E1                <1> 	shl	ecx, 1
  3240 00005EF7 51                  <1> 	push	ecx ; * 
  3241                              <1> 	;
  3242 00005EF8 89CB                <1> 	mov	ebx, ecx
  3243 00005EFA 8835[3D6F0000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3244 00005F00 31D2                <1> 	xor	edx, edx ; 0
  3245                              <1> 	; 09/01/2022
  3246                              <1> 	;sub	ecx, ecx 
  3247 00005F02 81C3[10660000]      <1>         add     ebx, drv.spt
  3248 00005F08 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3249                              <1> 		; EDX:EAX = LBA
  3250 00005F0B F7F1                <1> 	div	ecx
  3251 00005F0D 88D1                <1> 	mov	cl, dl	; sector number - 1
  3252 00005F0F FEC1                <1> 	inc	cl	; sector number (1 based)
  3253 00005F11 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3254                              <1> 	;push	cx
  3255                              <1>         ; 09/01/2022
  3256 00005F12 51                  <1> 	push	ecx
  3257 00005F13 81C3[02660000]      <1> 	add     ebx, drv.heads
  3258 00005F19 668B0B              <1> 	mov	cx, [ebx] ; heads
  3259 00005F1C 31D2                <1> 	xor	edx, edx
  3260                              <1> 		; EAX = cylinders * heads + head
  3261 00005F1E F7F1                <1> 	div	ecx
  3262                              <1> 	;pop	cx     ; sector number
  3263                              <1> 	; 09/01/2022
  3264 00005F20 59                  <1> 	pop	ecx
  3265 00005F21 88D6                <1> 	mov	dh, dl ; head number
  3266 00005F23 8A15[EB650000]      <1> 	mov	dl, [drv]
  3267 00005F29 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3268 00005F2B C0E406              <1> 	shl	ah, 6
  3269 00005F2E 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3270                              <1> 		       ; sector (bits 0-7)
  3271 00005F30 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3272                              <1> 		; CL = sector (bits 0-5)
  3273                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3274                              <1> 		; CH = cylinder (bits 0-7)
  3275                              <1> 		; DH = head
  3276                              <1> 		; DL = drive
  3277                              <1> 	;
  3278 00005F31 C605[3E6F0000]04    <1> 	mov	byte [retry_count], 4
  3279                              <1> rwdsk_retry:	
  3280 00005F38 8A25[3D6F0000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3281 00005F3E B001                <1> 	mov	al, 1 ; sector count	
  3282                              <1> 	;int	13h
  3283 00005F40 E858C6FFFF          <1> 	call	int13h
  3284 00005F45 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3285 00005F47 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3286 00005F49 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3287 00005F4C 7408                <1> 	je	short rwdsk_fails
  3288 00005F4E FE0D[3E6F0000]      <1> 	dec	byte [retry_count]
  3289 00005F54 7504                <1> 	jnz	short rwdsk_reset
  3290                              <1> rwdsk_fails:
  3291 00005F56 F9                  <1> 	stc
  3292                              <1> rwdsk_ok:
  3293 00005F57 5B                  <1> 	pop	ebx ; ***
  3294 00005F58 5E                  <1> 	pop	esi ; ****
  3295 00005F59 C3                  <1> 	retn
  3296                              <1> rwdsk_reset:
  3297                              <1> 	; 02/02/2015
  3298 00005F5A 28E4                <1> 	sub	ah, ah
  3299 00005F5C 80FA80              <1> 	cmp	dl, 80h
  3300 00005F5F 7202                <1> 	jb	short rwdsk_fd_reset
  3301 00005F61 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3302                              <1> rwdsk_fd_reset:
  3303                              <1> 	;int	13h
  3304 00005F63 E835C6FFFF          <1>         call	int13h
  3305 00005F68 73CE                <1> 	jnc	short rwdsk_retry
  3306 00005F6A 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3307 00005F6C EBE9                <1> 	jmp 	short rwdsk_ok
  3308                              <1> 
  3309                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3310                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3311                              <1> ;
  3312                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3313                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3314                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3315                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3316                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3317                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3318                              <1> ; as in original unix v1.
  3319                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3320                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3321                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3322                              <1> ;
  3323                              <1> ; Erdogan tan (10/07/2015) 
  3324                              <1> 
  3325                              <1> ;drum: / interrupt handler
  3326                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3327                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3328                              <1> ;                                      / error
  3329                              <1> ;               br 3f / no, error
  3330                              <1> ;       br      2f / error
  3331                              <1> ;
  3332                              <1> ;disk:
  3333                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3334                              <1> ;       jmp     *$0f
  3335                              <1> ;0:
  3336                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3337                              <1> ;      	        br 3f / no, errors
  3338                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3339                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3340                              <1> ;                        / to 1f
  3341                              <1> ;       br      4f
  3342                              <1> ;1:
  3343                              <1> ;       bit     $20000,rkcs
  3344                              <1> ;       beq     4f / wait for seek complete
  3345                              <1> ;       mov     $0b,0b-2
  3346                              <1> ;       mov     rkap,r1
  3347                              <1> ;2:
  3348                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3349                              <1> ;                          / the disk buffer
  3350                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3351                              <1> ;       inc     r1
  3352                              <1> ;       asr     (r1)
  3353                              <1> ;       asr     (r1)
  3354                              <1> ;       asr     (r1) / reissue request
  3355                              <1> ;       dec     r1
  3356                              <1> ;3:
  3357                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3358                              <1> ;       mov     ac,-(sp)
  3359                              <1> ;       mov     mq,-(sp) / put these on the stack
  3360                              <1> ;       mov     sc,-(sp)
  3361                              <1> ;       jsr     r0,poke
  3362                              <1> ;       mov     (sp)+,sc
  3363                              <1> ;       mov     (sp)+,mq / pop them off stack
  3364                              <1> ;       mov     (sp)+,ac
  3365                              <1> ;4:
  3366                              <1> ;       jmp     retisp / u4-3
  3367                              <1> ;
  3368                              <1> ;trapt:                  / r2 points to the
  3369                              <1> ;       mov     (r0)+,r2 / device control register
  3370                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3371                              <1> ;       tst     (sp)+
  3372                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3373                              <1> ;       bge     4b / device still active so branch
  3374                              <1> ;       bit     (r0),active / was device busy?
  3375                              <1> ;       beq     4b / no, stray interrupt
  3376                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3377                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3378                              <1> ;       bge     2f / if no error jump to 2f
  3379                              <1> ;       tst     (r0)+ / skip on error
  3380                              <1> ; 2:
  3381                              <1> ;       jmp     (r0)
  2096                                  %include 'u9.s'        ; 29/06/2015
  2097                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS9.INC
  2098                              <1> ; Last Modification: 16/02/2022
  2099                              <1> ; ----------------------------------------------------------------------------
  2100                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2101                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2102                              <1> ;
  2103                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2104                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2105                              <1> ; <Bell Laboratories (17/3/1972)>
  2106                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2107                              <1> ;
  2108                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2109                              <1> ;
  2110                              <1> ; ****************************************************************************
  2111                              <1> 
  2112                              <1> getch:
  2113                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2114                              <1> 	; 30/06/2015
  2115                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2116 00005F6E 28C0                <1> 	sub	al, al ; 0
  2117                              <1> getch_q: ; 06/08/2015
  2118 00005F70 8A25[266B0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2119 00005F76 EB06                <1>         jmp     short getc_n
  2120                              <1> 
  2121                              <1> getc: 
  2122                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2123                              <1> 	; 12/11/2015
  2124                              <1> 	; 15/09/2015
  2125                              <1> 	; 01/07/2015
  2126                              <1> 	; 30/06/2015
  2127                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2128                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2129                              <1> 	;
  2130                              <1> 	; Retro UNIX 8086 v1 modification !
  2131                              <1> 	; 
  2132                              <1> 	; 'getc' gets (next) character 
  2133                              <1> 	;	 from requested TTY (keyboard) buffer 
  2134                              <1> 	; INPUTS ->
  2135                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2136                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2137                              <1> 	;	(Keyboard buffer will point to 
  2138                              <1> 	;			next character at next call)
  2139                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2140                              <1> 	;	(Keyboard buffer will point to 
  2141                              <1> 	;			current character at next call)
  2142                              <1> 	; OUTPUTS ->
  2143                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2144                              <1> 	;     			 ZF=0 -> AX has (current) character
  2145                              <1> 	;      AL = ascii code
  2146                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2147                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2148                              <1> 	; Original UNIX V1 'getc': 
  2149                              <1> 	;		get a character off character list
  2150                              <1> 	;
  2151                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2152                              <1> 	;
  2153                              <1> 	; 30/06/2015 (32 bit modifications)
  2154                              <1> 	; 16/07/2013
  2155                              <1> 	; mov 	[getctty], ah
  2156                              <1> 	;
  2157                              <1> 
  2158 00005F78 8A25[0C6F0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2159                              <1> getc_n:
  2160                              <1> 	; 30/06/2015
  2161 00005F7E 08E4                <1> 	or	ah, ah
  2162 00005F80 740D                <1> 	jz	short getc0 
  2163 00005F82 D0E4                <1> 	shl	ah, 1
  2164 00005F84 0FB6DC              <1> 	movzx	ebx, ah
  2165 00005F87 81C3[286B0000]      <1> 	add	ebx, ttychr
  2166 00005F8D EB05                <1> 	jmp	short getc1
  2167                              <1> getc0:
  2168 00005F8F BB[286B0000]        <1> 	mov	ebx, ttychr
  2169                              <1> getc1:
  2170 00005F94 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2171                              <1> 				; (by kb_int)	
  2172 00005F97 6609C9              <1> 	or	cx, cx
  2173 00005F9A 7507                <1> 	jnz	short getc2
  2174 00005F9C 20C0                <1> 	and 	al, al
  2175 00005F9E 7415                <1> 	jz	short getc_s
  2176                              <1> 	;xor	ax, ax
  2177                              <1> 	; 24/12/2021
  2178 00005FA0 31C0                <1> 	xor	eax, eax
  2179 00005FA2 C3                  <1> 	retn
  2180                              <1> getc2:	
  2181 00005FA3 20C0                <1> 	and	al, al
  2182 00005FA5 6689C8              <1> 	mov	ax, cx
  2183 00005FA8 66B90000            <1> 	mov	cx, 0
  2184 00005FAC 7506                <1> 	jnz	short getc3
  2185                              <1> getc_sn:
  2186 00005FAE 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2187 00005FB1 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2188                              <1> getc3:
  2189 00005FB4 C3                  <1> 	retn
  2190                              <1> getc_s:
  2191                              <1> 	; 12/11/2015
  2192                              <1> 	; 15/09/2015
  2193                              <1> 	; 01/07/2015
  2194                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2195                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2196                              <1> 	;
  2197                              <1> 	; tty  of the current process is not 
  2198                              <1> 	; current tty (ptty); so, current process only 
  2199                              <1> 	; can use keyboard input when its tty becomes 
  2200                              <1> 	; current tty (ptty).
  2201                              <1> 	; 'sleep' is for preventing an endless lock
  2202                              <1> 	; during this tty input request.
  2203                              <1> 	; (Because, the user is not looking at the video page
  2204                              <1> 	; of the process to undersand there is a keyboard
  2205                              <1> 	; input request.)
  2206                              <1> 	;
  2207                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2208                              <1> 	;
  2209                              <1> 	; 05/10/2013
  2210                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2211                              <1> 	;
  2212                              <1> 	; 10/10/2013
  2213                              <1> gcw0:
  2214 00005FB5 B10A                <1> 	mov	cl, 10 ; ch = 0
  2215                              <1> gcw1:	
  2216                              <1> 	; 12/11/2015
  2217 00005FB7 E825DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2218                              <1> 	; 10/10/2013
  2219 00005FBC E86AEFFFFF          <1> 	call	idle
  2220 00005FC1 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2221                              <1> 				; (by kb_int)
  2222 00005FC4 6609C0              <1> 	or	ax, ax
  2223                              <1> ;	jnz	short gcw3
  2224 00005FC7 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2225                              <1> 	; 30/06/2015
  2226 00005FC9 FEC9                <1> 	dec	cl
  2227 00005FCB 75EA                <1> 	jnz	short gcw1
  2228                              <1> 	;
  2229 00005FCD 8A25[0C6F0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2230                              <1> ;	; 10/12/2013
  2231                              <1> ;	cmp 	ah, [ptty]
  2232                              <1> ;	jne	short gcw2
  2233                              <1> ;	; 14/02/2014
  2234                              <1> ;	cmp	byte [u.uno], 1
  2235                              <1> ;	jna	short gcw0		
  2236                              <1> ;gcw2:
  2237 00005FD3 E8E0EFFFFF          <1> 	call	sleep
  2238                              <1> 	;
  2239                              <1> 	; 20/09/2013
  2240 00005FD8 8A25[0C6F0000]      <1> 	mov	ah, [u.ttyn]
  2241 00005FDE 30C0                <1> 	xor 	al, al
  2242 00005FE0 EB9C                <1> 	jmp	short getc_n
  2243                              <1> ;gcw3:
  2244                              <1> gcw2: 	; 15/09/2015
  2245                              <1> 	; 10/10/2013
  2246 00005FE2 30C9                <1> 	xor	cl, cl
  2247 00005FE4 EBC8                <1> 	jmp	short getc_sn
  2248                              <1> 
  2249                              <1> putc:	
  2250                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2251                              <1> 	; 13/08/2015
  2252                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2253                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2254                              <1> 	;
  2255                              <1> 	; Retro UNIX 8086 v1 modification !
  2256                              <1> 	; 
  2257                              <1> 	; 'putc' puts a character 
  2258                              <1> 	;	 onto requested (tty) video page or
  2259                              <1> 	;	 serial port
  2260                              <1> 	; INPUTS ->
  2261                              <1> 	;     AL = ascii code of the character
  2262                              <1> 	;     AH = video page (tty) number (0 to 7)
  2263                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2264                              <1> 	; OUTPUTS ->
  2265                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2266                              <1> 	;      			ZF=0 -> AX has (current) character
  2267                              <1> 	;     cf=0 and AH = 0 -> no error
  2268                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2269                              <1> 	; 
  2270                              <1> 	; Original UNIX V1 'putc': 
  2271                              <1> 	;     put a character at the end of character list
  2272                              <1> 	;
  2273                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2274                              <1> 	;
  2275 00005FE6 80FC07              <1> 	cmp	ah, 7
  2276                              <1>         ;ja	sndc
  2277 00005FE9 770A                <1>         ja      short sndc ; 24/12/2024
  2278                              <1> 	; 30/06/2015
  2279 00005FEB 0FB6DC              <1> 	movzx	ebx, ah
  2280                              <1> 	; 13/08/2015
  2281 00005FEE B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2282 00005FF0 E9D2B3FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2283                              <1> 
  2284                              <1> sndc:   ; <Send character>
  2285                              <1> 	;
  2286                              <1> 	; 12/01/2022
  2287                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2288                              <1> 	; 17/11/2015
  2289                              <1> 	; 16/11/2015
  2290                              <1> 	; 11/11/2015
  2291                              <1> 	; 10/11/2015
  2292                              <1> 	; 09/11/2015
  2293                              <1> 	; 08/11/2015
  2294                              <1> 	; 07/11/2015
  2295                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2296                              <1> 	; 29/10/2015
  2297                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2298                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2299                              <1> 	;
  2300                              <1> 	; Retro UNIX 8086 v1 feature only !
  2301                              <1> 	;
  2302                              <1> 	; ah = [u.ttyn]
  2303                              <1> 	;
  2304                              <1> 	; 30/06/2015
  2305 00005FF5 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2306                              <1> 	; 07/11/2015
  2307 00005FF8 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2308                              <1> sndc0:
  2309                              <1> 	; 07/11/2015
  2310 00005FFB E806F0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2311 00006000 7405                <1> 	jz	short sndc1
  2312 00006002 E8DADBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2313                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2314                              <1> sndc1:
  2315                              <1> 	; 16/11/2015
  2316                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2317                              <1> 	; 24/12/2021
  2318 00006007 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2319                              <1> sndcx:
  2320 00006009 8A83[6A6B0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2321 0000600F 8AA3[686B0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2322                              <1> 	;
  2323                              <1> 	; 17/11/2015
  2324                              <1> 	; check 'request for response' status
  2325 00006015 80BB[646B0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2326 0000601C 740A                <1> 	jz	short query
  2327                              <1> response:
  2328 0000601E FE05[676B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2329 00006024 B0FF                <1> 	mov	al, 0FFh	 
  2330 00006026 EB14                <1> 	jmp	short sndc3
  2331                              <1> query:
  2332 00006028 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2333 0000602A 750E                <1> 	jnz 	short sndc2 ; normal character
  2334                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2335                              <1> 	;je	short sndc2  ; yes, already responded
  2336                              <1> 	; 16/11/2015
  2337                              <1> 	; query: request for response (again)
  2338 0000602C 8883[686B0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2339 00006032 FE05[676B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2340 00006038 EB02                <1> 	jmp	short sndc3
  2341                              <1> sndc2:
  2342 0000603A 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2343                              <1> sndc3:
  2344 0000603C 8883[6A6B0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2345 00006042 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2346                              <1> 	; 30/06/2015
  2347 00006044 E833D5FFFF          <1> 	call	sp_status ; get serial port status
  2348                              <1> 	; AL = Line status, AH = Modem status
  2349                              <1> 	; 07/11/2015
  2350 00006049 A880                <1> 	test	al, 80h
  2351 0000604B 7504                <1> 	jnz	short sndc4
  2352 0000604D A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2353 0000604F 751A                <1> 	jnz	short sndc5
  2354                              <1> sndc4: 	; Check line status again
  2355                              <1> 	; 16/11/2015
  2356                              <1> 	;push	cx
  2357                              <1> 	; 24/12/2021
  2358 00006051 51                  <1> 	push	ecx
  2359                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2360                              <1> 	; 12/01/2022
  2361 00006052 31C9                <1> 	xor	ecx, ecx
  2362 00006054 B106                <1> 	mov	cl, 6
  2363 00006056 E863B4FFFF          <1> 	call	WAITF
  2364                              <1> 	;pop	cx
  2365                              <1> 	; 24/12/1021
  2366 0000605B 59                  <1> 	pop	ecx
  2367                              <1> 	;
  2368 0000605C 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2369 0000605E E819D5FFFF          <1> 	call	sp_status ; get serial port status
  2370                              <1> 	; 16/11/2015
  2371                              <1> 	; 09/11/2015
  2372                              <1> 	; 08/11/2015
  2373 00006063 A880                <1> 	test	al, 80h	; time out error
  2374 00006065 7565                <1>         jnz     short sndc7
  2375 00006067 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2376 00006069 7461                <1>         jz	short sndc7
  2377                              <1> sndc5:  
  2378 0000606B 8A83[6A6B0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2379 00006071 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2380 00006075 28DE                <1> 	sub	dh, bl
  2381 00006077 EE                  <1> 	out	dx, al	   ; send on serial port
  2382                              <1> 	; 10/11/2015
  2383                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2384                              <1> 	; (to improve text flow to the terminal)
  2385                              <1> 	; ('diskette.inc': 'WAITF')
  2386                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2387                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2388                              <1> 	;push	cx
  2389                              <1> 	; 24/12/2021
  2390 00006078 51                  <1> 	push	ecx
  2391                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2392                              <1> 	; 12/01/2022
  2393 00006079 29C9                <1> 	sub	ecx, ecx
  2394 0000607B B106                <1> 	mov	cl, 6
  2395 0000607D E83CB4FFFF          <1> 	call	WAITF
  2396                              <1> 	;pop	cx
  2397                              <1> 	; 24/12/1021
  2398 00006082 59                  <1> 	pop	ecx
  2399                              <1>     	;
  2400                              <1> 	; 07/11/2015
  2401 00006083 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2402                              <1> 	;
  2403 00006085 E8F2D4FFFF          <1> 	call	sp_status ; get serial port status
  2404                              <1> 	; AL = Line status, AH = Modem status
  2405                              <1> 	;
  2406 0000608A E877EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2407 0000608F 7405                <1> 	jz	short sndc6
  2408 00006091 E84BDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2409                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2410                              <1> sndc6:
  2411 00006096 3C80                <1> 	cmp	al, 80h
  2412 00006098 7332                <1> 	jnb	short sndc7		
  2413                              <1> 	;
  2414 0000609A 803D[676B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2415 000060A1 7244                <1> 	jb	short sndc8 	; no, normal character
  2416 000060A3 883D[676B0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2417                              <1> 	; 17/11/2015
  2418 000060A9 E87DEEFFFF          <1> 	call	idle
  2419                              <1> 	;
  2420 000060AE 38BB[6A6B0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2421                              <1>         ;ja	sndc2       ; response (will be followed by
  2422                              <1> 			    ; a normal character)
  2423                              <1> 	; 24/12/2021
  2424 000060B4 7602                <1> 	jna	short sndc_10
  2425 000060B6 EB82                <1> 	jmp	sndc2
  2426                              <1> sndc_10:
  2427                              <1> 	; Query request must be responded by the terminal
  2428                              <1> 	; before sending a normal character !
  2429 000060B8 53                  <1> 	push	ebx
  2430                              <1> 	;push	cx ; *** cl = character (to be sent)
  2431                              <1> 	; 24/12/2021
  2432 000060B9 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2433 000060BA 8A25[0C6F0000]      <1> 	mov	ah, [u.ttyn]
  2434 000060C0 E8F3EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2435                              <1> 		      ; received data available interrupt
  2436                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2437                              <1> 	; 24/12/2021
  2438 000060C5 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2439 000060C6 5B                  <1> 	pop	ebx
  2440 000060C7 E93DFFFFFF          <1>         jmp	sndcx
  2441                              <1> sndc7:
  2442                              <1> 	 ; 16/11/2015
  2443 000060CC 803D[676B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2444 000060D3 7213                <1> 	jb	short sndc9 	; no
  2445                              <1> 	;
  2446 000060D5 88BB[686B0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2447 000060DB 88BB[6A6B0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2448                              <1> 	;
  2449 000060E1 883D[676B0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2450                              <1> sndc8:
  2451 000060E7 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2452                              <1> sndc9:
  2453                              <1> 	; AL = Line status, AH = Modem status
  2454 000060E8 C3                  <1> 	retn
  2455                              <1> 
  2456                              <1> get_cpos:
  2457                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2458                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2459                              <1> 	;
  2460                              <1> 	; INPUT -> bl = video page number
  2461                              <1> 	; RETURN -> dx = cursor position
  2462                              <1> 
  2463 000060E9 53                  <1> 	push	ebx
  2464 000060EA 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2465 000060ED D0E3                <1> 	shl	bl, 1
  2466 000060EF 81C3[166B0000]      <1> 	add	ebx, cursor_posn
  2467 000060F5 668B13              <1> 	mov	dx, [ebx]
  2468 000060F8 5B                  <1> 	pop	ebx
  2469 000060F9 C3                  <1> 	retn
  2470                              <1> 
  2471                              <1> read_ac_current:
  2472                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2473                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2474                              <1> 	;
  2475                              <1> 	; INPUT -> bl = video page number
  2476                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2477                              <1> 
  2478 000060FA E832B4FFFF          <1> 	call 	find_position ; 'video.inc'
  2479                              <1> 	; dx = status port
  2480                              <1> 	; esi = cursor location/address
  2481 000060FF 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2482 00006105 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2483 00006108 C3                  <1> 	retn
  2484                              <1> 
  2485                              <1> syssleep:
  2486                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2487                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2488                              <1> 	;
  2489                              <1> 	; Retro UNIX 8086 v1 feature only
  2490                              <1> 	; (INPUT -> none)
  2491                              <1> 	;
  2492 00006109 0FB61D[076F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2493 00006110 8AA3[176C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2494 00006116 E89DEEFFFF          <1> 	call	sleep
  2495 0000611B E9D4D9FFFF          <1> 	jmp	sysret
  2496                              <1> 
  2497                              <1> vp_clr:
  2498                              <1> 	; Reset/Clear Video Page
  2499                              <1> 	;
  2500                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2501                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2502                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2503                              <1> 	;
  2504                              <1> 	; Retro UNIX 8086 v1 feature only !
  2505                              <1> 	;
  2506                              <1> 	; INPUTS -> 
  2507                              <1> 	;   BL = video page number	 
  2508                              <1> 	;
  2509                              <1> 	; OUTPUT ->
  2510                              <1> 	;   none
  2511                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2512                              <1> 	;
  2513                              <1> 	; 04/12/2013
  2514 00006120 28C0                <1> 	sub	al, al
  2515                              <1> 	; al = 0 (clear video page)
  2516                              <1> 	; bl = video page
  2517 00006122 B407                <1> 	mov	ah, 07h
  2518                              <1> 	; ah = 7 (attribute/color)
  2519                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2520                              <1> 	; 24/12/2021
  2521 00006124 31C9                <1> 	xor	ecx, ecx
  2522 00006126 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2523 0000612A E82CB4FFFF          <1> 	call	scroll_up
  2524                              <1> 	; bl = video page
  2525                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2526                              <1> 	; 24/12/2021
  2527 0000612F 31D2                <1> 	xor	edx, edx 
  2528 00006131 E99BB3FFFF          <1> 	jmp 	set_cpos
  2529                              <1> 
  2530                              <1> sysmsg:
  2531                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2532                              <1> 	; 11/11/2015
  2533                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2534                              <1> 	; Print user-application message on user's console tty
  2535                              <1> 	;
  2536                              <1> 	; Input -> EBX = Message address
  2537                              <1> 	;	   ECX = Message length (max. 255)
  2538                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2539                              <1> 	;
  2540 00006136 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2541                              <1> 	;ja	sysret ; nothing to do with big message size
  2542 0000613C 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2543 0000613E 08C9                <1> 	or	cl, cl
  2544                              <1> 	;jz	sysret
  2545 00006140 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2546 00006142 20D2                <1> 	and	dl, dl
  2547 00006144 7502                <1> 	jnz	short sysmsg0
  2548 00006146 B207                <1> 	mov	dl, 07h ; default color
  2549                              <1> 		; (black background, light gray character)
  2550                              <1> sysmsg0:
  2551 00006148 891D[D86E0000]      <1> 	mov	[u.base], ebx
  2552 0000614E 8815[276B0000]      <1> 	mov	[ccolor], dl ; color attributes
  2553 00006154 89E5                <1> 	mov	ebp, esp
  2554 00006156 31DB                <1> 	xor	ebx, ebx ; 0
  2555 00006158 891D[E06E0000]      <1> 	mov	[u.nread], ebx ; 0
  2556                              <1> 	;
  2557 0000615E 381D[1F6F0000]      <1> 	cmp	[u.kcall], bl ; 0
  2558 00006164 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2559                              <1> 	;
  2560 00006166 890D[DC6E0000]      <1> 	mov	[u.count], ecx
  2561 0000616C 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2562                              <1> 	; 24/12/2021
  2563                              <1> 	; (dword alignment for esp)
  2564 0000616D F6C103              <1> 	test	cl, 3
  2565 00006170 7404                <1> 	jz	short sysmsg_7
  2566 00006172 80C903              <1> 	or	cl, 3
  2567 00006175 41                  <1> 	inc	ecx
  2568                              <1> sysmsg_7:
  2569 00006176 29CC                <1> 	sub	esp, ecx
  2570 00006178 89E7                <1> 	mov	edi, esp
  2571 0000617A 89E6                <1> 	mov	esi, esp
  2572 0000617C 66891D[1D6F0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2573                              <1> 	; 11/11/2015
  2574 00006183 8A25[E86E0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2575                              <1> 	; 0 = none
  2576 00006189 FECC                <1> 	dec	ah
  2577 0000618B 790C                <1> 	jns	short sysmsg1 
  2578 0000618D 8A1D[076F0000]      <1> 	mov	bl, [u.uno] ; process number	
  2579 00006193 8AA3[176C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2580                              <1> sysmsg1:
  2581 00006199 8825[0C6F0000]      <1> 	mov	[u.ttyn], ah
  2582                              <1> sysmsg2:
  2583 0000619F E86AF5FFFF          <1> 	call	cpass
  2584 000061A4 7416                <1> 	jz	short sysmsg5
  2585 000061A6 AA                  <1> 	stosb
  2586 000061A7 20C0                <1> 	and	al, al
  2587 000061A9 75F4                <1> 	jnz	short sysmsg2
  2588                              <1> sysmsg3:
  2589 000061AB 80FC07              <1> 	cmp	ah, 7 ; tty number
  2590 000061AE 7711                <1> 	ja	short sysmsg6 ; serial port
  2591 000061B0 E83E000000          <1> 	call	print_cmsg
  2592                              <1> sysmsg4:
  2593 000061B5 89EC                <1> 	mov	esp, ebp	
  2594                              <1> sysmsg8: ; 24/12/2021	
  2595 000061B7 E938D9FFFF          <1> 	jmp	sysret
  2596                              <1> sysmsg5:
  2597 000061BC C60700              <1> 	mov	byte [edi], 0
  2598 000061BF EBEA                <1> 	jmp	short sysmsg3
  2599                              <1> sysmsg6:
  2600 000061C1 8A06                <1> 	mov	al, [esi]
  2601 000061C3 E82DFEFFFF          <1> 	call	sndc
  2602 000061C8 72EB                <1> 	jc	short sysmsg4
  2603 000061CA 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2604 000061CD 76E6                <1> 	jna	short sysmsg4
  2605 000061CF 46                  <1> 	inc 	esi
  2606 000061D0 8A25[0C6F0000]      <1> 	mov	ah, [u.ttyn]
  2607 000061D6 EBE9                <1> 	jmp	short sysmsg6
  2608                              <1> 
  2609                              <1> sysmsgk: ; Temporary (01/07/2015)
  2610                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2611                              <1> 	; (ECX -character count- will not be considered)
  2612 000061D8 8B35[D86E0000]      <1> 	mov	esi, [u.base]
  2613 000061DE 8A25[266B0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2614 000061E4 8825[0C6F0000]      <1> 	mov	[u.ttyn], ah
  2615 000061EA C605[1F6F0000]00    <1> 	mov	byte [u.kcall], 0
  2616 000061F1 EBB8                <1> 	jmp	short sysmsg3
  2617                              <1> 	
  2618                              <1> print_cmsg: 
  2619                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2620                              <1> 	;
  2621                              <1> 	; print message (on user's console tty) 
  2622                              <1> 	;	with requested color
  2623                              <1> 	;
  2624                              <1> 	; INPUTS:
  2625                              <1> 	;	esi = message address
  2626                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2627                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2628                              <1> 	;
  2629 000061F3 AC                  <1> 	lodsb
  2630                              <1> pcmsg1:
  2631 000061F4 56                  <1> 	push 	esi
  2632 000061F5 0FB61D[0C6F0000]    <1>         movzx   ebx, byte [u.ttyn]
  2633 000061FC 8A25[276B0000]      <1> 	mov	ah, [ccolor]
  2634 00006202 E8C0B1FFFF          <1> 	call 	write_tty
  2635 00006207 5E                  <1> 	pop	esi
  2636 00006208 AC                  <1> 	lodsb
  2637 00006209 20C0                <1> 	and 	al, al  ; 0
  2638 0000620B 75E7                <1> 	jnz 	short pcmsg1
  2639 0000620D C3                  <1> 	retn
  2640                              <1> 
  2641                              <1> sysgeterr:
  2642                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.1
  2643                              <1> 	; 09/12/2015
  2644                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2645                              <1> 	; Get last error number or page fault count
  2646                              <1> 	; (for debugging)
  2647                              <1> 	;
  2648                              <1> 	; Input -> EBX = return type
  2649                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2650                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2651                              <1> 	;	   FFFFFFFEh = total page fault count
  2652                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2653                              <1> 	;
  2654                              <1> 	; Output -> EAX = last error number or page fault count
  2655                              <1> 	;	   (depending on EBX input)
  2656                              <1> 	; 	
  2657 0000620E 21DB                <1> 	and 	ebx, ebx
  2658 00006210 750F                <1> 	jnz	short glerr_2
  2659                              <1> glerr_0:
  2660 00006212 A1[0D6F0000]        <1> 	mov	eax, [u.error]
  2661                              <1> glerr_1:
  2662 00006217 A3[B86E0000]        <1> 	mov	[u.r0], eax
  2663                              <1>  	;retn
  2664                              <1> 	; 16/02/2022 (BugFix)
  2665 0000621C E9D3D8FFFF          <1> 	jmp	sysret
  2666                              <1> glerr_2:
  2667 00006221 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2668 00006222 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2669 00006224 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2670 00006225 75EB                <1> 	jnz	short glerr_0
  2671 00006227 A1[B06B0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2672 0000622C EBE9                <1>         jmp     short glerr_1
  2673                              <1> glerr_3:
  2674 0000622E A1[216F0000]        <1> 	mov 	eax, [u.pfcount]
  2675 00006233 EBE2                <1> 	jmp	short glerr_1
  2097                                  
  2098                                  ; 07/03/2015
  2099                                  ; Temporary Code
  2100                                  display_disks:
  2101 00006235 803D[EE650000]00        	cmp 	byte [fd0_type], 0
  2102 0000623C 7605                    	jna 	short ddsks1
  2103 0000623E E87D000000              	call	pdskm
  2104                                  ddsks1:
  2105 00006243 803D[EF650000]00        	cmp	byte [fd1_type], 0
  2106 0000624A 760C                    	jna	short ddsks2
  2107 0000624C C605[DF670000]31        	mov	byte [dskx], '1'
  2108 00006253 E868000000              	call	pdskm
  2109                                  ddsks2:
  2110 00006258 803D[F0650000]00        	cmp	byte [hd0_type], 0
  2111 0000625F 7654                    	jna	short ddsk6
  2112 00006261 66C705[DD670000]68-     	mov	word [dsktype], 'hd'
  2112 00006269 64                 
  2113 0000626A C605[DF670000]30        	mov	byte [dskx], '0'
  2114 00006271 E84A000000              	call	pdskm
  2115                                  ddsks3:
  2116 00006276 803D[F1650000]00        	cmp	byte [hd1_type], 0
  2117 0000627D 7636                    	jna	short ddsk6
  2118 0000627F C605[DF670000]31        	mov	byte [dskx], '1'
  2119 00006286 E835000000              	call	pdskm
  2120                                  ddsks4:
  2121 0000628B 803D[F2650000]00        	cmp	byte [hd2_type], 0
  2122 00006292 7621                    	jna	short ddsk6
  2123 00006294 C605[DF670000]32        	mov	byte [dskx], '2'
  2124 0000629B E820000000              	call	pdskm
  2125                                  ddsks5:
  2126 000062A0 803D[F3650000]00        	cmp	byte [hd3_type], 0
  2127 000062A7 760C                    	jna	short ddsk6
  2128 000062A9 C605[DF670000]33        	mov	byte [dskx], '3'
  2129 000062B0 E80B000000              	call	pdskm
  2130                                  ddsk6:
  2131 000062B5 BE[EE670000]            	mov	esi, nextline
  2132 000062BA E806000000              	call	pdskml
  2133                                  pdskm_ok:
  2134 000062BF C3                      	retn
  2135                                  pdskm:
  2136 000062C0 BE[DB670000]            	mov	esi, dsk_ready_msg
  2137                                  pdskml:	
  2138 000062C5 AC                      	lodsb
  2139 000062C6 08C0                    	or	al, al
  2140 000062C8 74F5                    	jz	short pdskm_ok
  2141 000062CA 56                      	push	esi
  2142 000062CB 31DB                    	xor	ebx, ebx ; 0
  2143                                  			; Video page 0 (bl=0)
  2144 000062CD B407                    	mov	ah, 07h ; Black background, 
  2145                                  			; light gray forecolor
  2146 000062CF E8F3B0FFFF              	call	write_tty
  2147 000062D4 5E                      	pop	esi
  2148 000062D5 EBEE                    	jmp	short pdskml
  2149                                  
  2150 000062D7 90<rep 9h>              align 16
  2151                                  
  2152                                  gdt:	; Global Descriptor Table
  2153                                  	; (30/07/2015, conforming cs)
  2154                                  	; (26/03/2015)
  2155                                  	; (24/03/2015, tss)
  2156                                  	; (19/03/2015)
  2157                                  	; (29/12/2013)
  2158                                  	;
  2159 000062E0 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2160                                  	; 18/08/2014
  2161                                  			; 8h kernel code segment, base = 00000000h		
  2162 000062E8 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2163                                  			; 10h kernel data segment, base = 00000000h	
  2164 000062F0 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2165                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2166 000062F8 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2167                                  			; 23h user data segment, base address = 400000h ; CORE
  2168 00006300 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2169                                  			; Task State Segment
  2170 00006308 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2171                                  			       ;  no IO permission in ring 3)
  2172                                  gdt_tss0:
  2173 0000630A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2174                                  gdt_tss1:
  2175 0000630C 00                      	db 0  ; TSS base address, bits 16-23 
  2176                                  	      		; 49h	
  2177 0000630D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2178 0000630E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2179                                  gdt_tss2:
  2180 0000630F 00                      	db 0  ; TSS base address, bits 24-31 
  2181                                  
  2182                                  gdt_end:
  2183                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2184                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2185                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2186                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2187                                  
  2188                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2189                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2190                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2191                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2192                                  		; W= Writeable, A= Accessed
  2193                                  	
  2194                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2195                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2196                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2197                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2198                                  
  2199                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2200                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2201                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2202                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2203                                  	
  2204                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2205                                  
  2206                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2207                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2208                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2209                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2210                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2211                                  		; AVL= Available to programmers	
  2212                                  
  2213                                  gdtd:
  2214 00006310 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2215 00006312 [E0620000]                      dd gdt			; Address of the GDT
  2216                                  
  2217                                  	; 20/08/2014
  2218                                  idtd:
  2219 00006316 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2220 00006318 [90680000]                      dd idt			; Address of the IDT
  2221                                  
  2222                                  Align 4
  2223                                  
  2224                                  	; 21/08/2014
  2225                                  ilist:
  2226                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2227                                  	;
  2228                                  	; Exception list
  2229                                  	; 25/08/2014	
  2230 0000631C [26080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2231 00006320 [2D080000]              	dd	exc1	
  2232 00006324 [34080000]              	dd 	exc2	
  2233 00006328 [3B080000]              	dd	exc3	
  2234 0000632C [3F080000]              	dd	exc4	
  2235 00006330 [43080000]              	dd	exc5	
  2236 00006334 [47080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2237 00006338 [4B080000]              	dd	exc7	
  2238 0000633C [4F080000]              	dd	exc8	
  2239 00006340 [53080000]              	dd	exc9	
  2240 00006344 [57080000]              	dd 	exc10	
  2241 00006348 [5B080000]              	dd	exc11
  2242 0000634C [5F080000]              	dd	exc12
  2243 00006350 [63080000]              	dd	exc13	; 0Dh, General Protection Fault
  2244 00006354 [67080000]              	dd 	exc14	; 0Eh, Page Fault
  2245 00006358 [6B080000]              	dd	exc15
  2246 0000635C [6F080000]              	dd	exc16
  2247 00006360 [73080000]              	dd	exc17
  2248 00006364 [77080000]              	dd 	exc18
  2249 00006368 [7B080000]              	dd	exc19
  2250 0000636C [7F080000]              	dd 	exc20
  2251 00006370 [83080000]              	dd	exc21
  2252 00006374 [87080000]              	dd	exc22
  2253 00006378 [8B080000]              	dd	exc23
  2254 0000637C [8F080000]              	dd 	exc24
  2255 00006380 [93080000]              	dd	exc25
  2256 00006384 [97080000]              	dd	exc26
  2257 00006388 [9B080000]              	dd	exc27
  2258 0000638C [9F080000]              	dd 	exc28
  2259 00006390 [A3080000]              	dd	exc29
  2260 00006394 [A7080000]              	dd 	exc30
  2261 00006398 [AB080000]              	dd	exc31
  2262                                  	; Interrupt list
  2263 0000639C [61060000]              	dd	timer_int	; INT 20h
  2264                                  		;dd	irq0	
  2265 000063A0 [650B0000]              	dd	keyb_int	; 27/08/2014
  2266                                  		;dd	irq1
  2267 000063A4 [80070000]              	dd	irq2
  2268                                  		; COM2 int
  2269 000063A8 [84070000]              	dd	irq3
  2270                                  		; COM1 int
  2271 000063AC [8F070000]              	dd	irq4
  2272 000063B0 [9A070000]              	dd	irq5
  2273                                  ;DISKETTE_INT: ;06/02/2015
  2274 000063B4 [4A250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2275                                  		;dd	irq6
  2276                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2277                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2278 000063B8 [160B0000]              	dd	default_irq7	; 25/02/2015
  2279                                  		;dd	irq7
  2280                                  ; Real Time Clock Interrupt
  2281 000063BC [B4090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2282                                  		;dd	irq8	; INT 28h
  2283 000063C0 [AA070000]              	dd	irq9
  2284 000063C4 [AE070000]              	dd	irq10
  2285 000063C8 [B2070000]              	dd	irq11
  2286 000063CC [B6070000]              	dd	irq12
  2287 000063D0 [BA070000]              	dd	irq13
  2288                                  ;HDISK_INT1:  ;06/02/2015 	
  2289 000063D4 [712D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2290                                  		;dd	irq14
  2291                                  ;HDISK_INT2:  ;06/02/2015
  2292 000063D8 [942D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2293                                  		;dd	irq15	; INT 2Fh
  2294                                  		; 14/08/2015
  2295 000063DC [DC390000]              	dd	sysent		; INT 30h (system calls)
  2296                                  	
  2297                                  	;dd	ignore_int
  2298 000063E0 00000000                	dd	0
  2299                                  
  2300                                  ;;;
  2301                                  ;;; 11/03/2015
  2302                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2303                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2304                              <1> ; Last Modification: 11/03/2015
  2305                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2306                              <1> ;
  2307                              <1> ; ///////// KEYBOARD DATA ///////////////
  2308                              <1> 
  2309                              <1> ; 05/12/2014
  2310                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2311                              <1> ; 03/06/86  KEYBOARD BIOS
  2312                              <1> 
  2313                              <1> ;---------------------------------------------------------------------------------
  2314                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2315                              <1> ;---------------------------------------------------------------------------------
  2316                              <1> 
  2317                              <1> ;-----	TABLES FOR ALT CASE ------------
  2318                              <1> ;-----	ALT-INPUT-TABLE 
  2319 000063E4 524F50514B          <1> K30:	db	82,79,80,81,75
  2320 000063E9 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2321                              <1> ;-----	SUPER-SHIFT-TABLE 
  2322 000063EE 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2323 000063F4 161718191E1F        <1> 	db	22,23,24,25,30,31
  2324 000063FA 202122232425        <1> 	db	32,33,34,35,36,37
  2325 00006400 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2326 00006406 3132                <1> 	db	49,50
  2327                              <1> 
  2328                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2329                              <1> ;-----	KEY_TABLE 
  2330 00006408 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2331 00006409 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2332 0000640E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2333                              <1> _K6L    equ     $-_K6
  2334                              <1> 
  2335                              <1> ;-----	MASK_TABLE
  2336 00006410 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2337 00006411 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2338 00006416 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2339                              <1> 
  2340                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2341 00006418 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2342 0000641E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2343 00006424 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2344 0000642A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2345 00006430 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2346 00006436 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2347 0000643C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2348 00006442 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2349 00006448 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2350 0000644E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2351                              <1> 	;				;----- FUNCTIONS ------		
  2352 00006452 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2353 00006458 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2354 0000645E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2355 00006464 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2356 0000646A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2357                              <1> 
  2358                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2359 00006470 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2359 00006479 39302D3D0809        <1>
  2360 0000647F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2360 00006488 705B5D0DFF61736466- <1>
  2360 00006491 67686A6B6C3B27      <1>
  2361 00006498 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2361 000064A1 6D2C2E2FFF2AFF20FF  <1>
  2362                              <1> ;-----	LC TABLE SCAN
  2363 000064AA 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2364 000064AF 4041424344          <1> 	db	64,65,66,67,68
  2365 000064B4 FFFF                <1> 	db	-1,-1			; NL, SL
  2366                              <1> 
  2367                              <1> ;-----	KEYPAD TABLE
  2368 000064B6 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2369 000064BC 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2370 000064C3 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2371                              <1> 
  2372                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2373 000064C8 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2373 000064D1 28295F2B0800        <1>
  2374 000064D7 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2374 000064E0 507B7D0DFF41534446- <1>
  2374 000064E9 47484A4B4C3A22      <1>
  2375 000064F0 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2375 000064F9 4D3C3E3FFF2AFF20FF  <1>
  2376                              <1> ;-----	UC TABLE SCAN
  2377 00006502 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2378 00006507 595A5B5C5D          <1> 	db	89,90,91,92,93
  2379 0000650C FFFF                <1> 	db	-1,-1			; NL, SL
  2380                              <1> 
  2381                              <1> ;-----	NUM STATE TABLE
  2382 0000650E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2382 00006517 3233302E            <1>
  2383                              <1> 	;
  2384 0000651B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2385                              <1> 
  2386                              <1> Align	4
  2387                              <1> ;----------------------------------------
  2388                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2389                              <1> ;----------------------------------------
  2390 00006520 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2391 00006521 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2392                              <1> 				; (29h default setting for video mode 3)
  2393                              <1> 				; Mode Select register Bits
  2394                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2395                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2396                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2397                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2398                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2399                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2400                              <1> 				;   BIT 6, 7 - Not Used
  2401                              <1> 
  2402                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2403                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2404                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2405                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2406                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2407                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2408                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2409                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2410                              <1> ; Mode & 37h = Video signal OFF
  2411                              <1> 			
  2412                              <1> 
  2413                              <1> ; 26/08/2014
  2414                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2415                              <1> ; Derived from IBM "pc-at" 
  2416                              <1> ; rombios source code (06/10/1985)
  2417                              <1> ; 'dseg.inc'
  2418                              <1> 
  2419                              <1> ;---------------------------------------;
  2420                              <1> ;	SYSTEM DATA AREA		;
  2421                              <1> ;----------------------------------------
  2422 00006522 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2423                              <1> 
  2424                              <1> ;----------------------------------------
  2425                              <1> ;	KEYBOARD DATA AREAS		;
  2426                              <1> ;----------------------------------------
  2427                              <1> 
  2428 00006523 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2429 00006524 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2430 00006525 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2431 00006526 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2432 00006527 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2433 00006528 [38650000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2434 0000652C [58650000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2435 00006530 [38650000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2436 00006534 [38650000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2437                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2438 00006538 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2439                              <1> 
  2440                              <1> ; /// End Of KEYBOARD DATA ///
  2303                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2304                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2305                              <1> ; Last Modification: 11/03/2015
  2306                              <1> ;		    (Data section for 'VIDEO.INC')	
  2307                              <1> ;
  2308                              <1> ; ///////// VIDEO DATA ///////////////
  2309                              <1> 
  2310                              <1> video_params:
  2311                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2312                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2313                              <1> 	; VIDEO MODE 3
  2314 00006558 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2315 0000655F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2316 00006564 00000000            <1> 	db	0,0,0,0
  2317                              <1> 
  2318                              <1> ; /// End Of VIDEO DATA ///
  2304                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2305                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2306                              <1> ; Last Modification: 11/03/2015
  2307                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2308                              <1> ;
  2309                              <1> ; *****************************************************************************
  2310                              <1> 
  2311                              <1> ;----------------------------------------
  2312                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2313                              <1> ;	REFERENCED BY POST & BIOS	:
  2314                              <1> ;----------------------------------------
  2315                              <1> 
  2316 00006568 [CB650000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2317                              <1> 
  2318                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2319                              <1> ;----------------------------------------------------------------
  2320                              <1> ; DISK_BASE							:
  2321                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2322                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2323                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2324                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2325                              <1> ;----------------------------------------------------------------
  2326                              <1> 
  2327                              <1> ;DISK_BASE:	
  2328                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2329                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2330                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2331                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2332                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2333                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2334                              <1> ;	DB	01BH		; GAP LENGTH
  2335                              <1> ;	DB	0FFH		; DTL
  2336                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2337                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2338                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2339                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2340                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2341                              <1> 
  2342                              <1> ;----------------------------------------
  2343                              <1> ;	ROM BIOS DATA AREAS		:
  2344                              <1> ;----------------------------------------
  2345                              <1> 
  2346                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2347                              <1> 
  2348                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2349                              <1> 
  2350                              <1> ;----------------------------------------
  2351                              <1> ;	DISKETTE DATA AREAS		:
  2352                              <1> ;----------------------------------------
  2353                              <1> 
  2354                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2355                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2356                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2357                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2358                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2359                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2360                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2361                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2362                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2363                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2364                              <1> 
  2365                              <1> ;----------------------------------------
  2366                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2367                              <1> ;----------------------------------------
  2368                              <1> 
  2369                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2370                              <1> 
  2371                              <1> ;----------------------------------------
  2372                              <1> ;	TIMER DATA AREA 		:
  2373                              <1> ;----------------------------------------
  2374                              <1> 
  2375                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2376                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2377                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2378                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2379                              <1> 
  2380                              <1> ;----------------------------------------
  2381                              <1> ;	ADDITIONAL MEDIA DATA		:
  2382                              <1> ;----------------------------------------
  2383                              <1> 
  2384                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2385                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2386                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2387                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2388                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2389                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2390                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2391                              <1> 
  2392                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2393                              <1> 
  2394                              <1> ;--------------------------------------------------------
  2395                              <1> ;	DRIVE TYPE TABLE				:
  2396                              <1> ;--------------------------------------------------------
  2397                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2398                              <1> DR_TYPE:
  2399 0000656C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2400                              <1>                 ;DW      MD_TBL1
  2401 0000656D [8A650000]          <1> 		dd	MD_TBL1
  2402 00006571 82                  <1> 		DB	02+BIT7ON
  2403                              <1> 		;DW      MD_TBL2
  2404 00006572 [97650000]          <1>                 dd      MD_TBL2
  2405 00006576 02                  <1> DR_DEFAULT:	DB	02
  2406                              <1>                 ;DW      MD_TBL3
  2407 00006577 [A4650000]          <1> 		dd      MD_TBL3
  2408 0000657B 03                  <1> 		DB	03
  2409                              <1>                 ;DW      MD_TBL4
  2410 0000657C [B1650000]          <1> 		dd      MD_TBL4
  2411 00006580 84                  <1> 		DB	04+BIT7ON
  2412                              <1>                 ;DW      MD_TBL5
  2413 00006581 [BE650000]          <1> 		dd      MD_TBL5
  2414 00006585 04                  <1> 		DB	04
  2415                              <1>                 ;DW      MD_TBL6
  2416 00006586 [CB650000]          <1> 		dd      MD_TBL6
  2417                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2418                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2419                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2420                              <1> ;--------------------------------------------------------
  2421                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2422                              <1> ;--------------------------------------------------------
  2423                              <1> ;--------------------------------------------------------
  2424                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2425                              <1> ;--------------------------------------------------------
  2426                              <1> MD_TBL1:        
  2427 0000658A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2428 0000658B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2429 0000658C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2430 0000658D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2431 0000658E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2432 0000658F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2433 00006590 FF                  <1> 	DB	0FFH		; DTL
  2434 00006591 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2435 00006592 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2436 00006593 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2437 00006594 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2438 00006595 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2439 00006596 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2440                              <1> ;--------------------------------------------------------
  2441                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2442                              <1> ;--------------------------------------------------------
  2443                              <1> MD_TBL2:        
  2444 00006597 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2445 00006598 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2446 00006599 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2447 0000659A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2448 0000659B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2449 0000659C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2450 0000659D FF                  <1> 	DB	0FFH		; DTL
  2451 0000659E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2452 0000659F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2453 000065A0 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2454 000065A1 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2455 000065A2 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2456 000065A3 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2457                              <1> ;--------------------------------------------------------
  2458                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2459                              <1> ;--------------------------------------------------------
  2460                              <1> MD_TBL3:
  2461 000065A4 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2462 000065A5 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2463 000065A6 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2464 000065A7 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2465 000065A8 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2466 000065A9 1B                  <1> 	DB	01BH		; GAP LENGTH
  2467 000065AA FF                  <1> 	DB	0FFH		; DTL
  2468 000065AB 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2469 000065AC F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2470 000065AD 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2471 000065AE 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2472 000065AF 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2473 000065B0 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2474                              <1> ;--------------------------------------------------------
  2475                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2476                              <1> ;--------------------------------------------------------
  2477                              <1> MD_TBL4:
  2478 000065B1 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2479 000065B2 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2480 000065B3 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2481 000065B4 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2482 000065B5 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2483 000065B6 2A                  <1> 	DB	02AH		; GAP LENGTH
  2484 000065B7 FF                  <1> 	DB	0FFH		; DTL
  2485 000065B8 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2486 000065B9 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2487 000065BA 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2488 000065BB 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2489 000065BC 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2490 000065BD 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2491                              <1> ;--------------------------------------------------------
  2492                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2493                              <1> ;--------------------------------------------------------
  2494                              <1> MD_TBL5:
  2495 000065BE DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2496 000065BF 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2497 000065C0 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2498 000065C1 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2499 000065C2 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2500 000065C3 2A                  <1> 	DB	02AH		; GAP LENGTH
  2501 000065C4 FF                  <1> 	DB	0FFH		; DTL
  2502 000065C5 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2503 000065C6 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2504 000065C7 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2505 000065C8 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2506 000065C9 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2507 000065CA 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2508                              <1> ;--------------------------------------------------------
  2509                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2510                              <1> ;--------------------------------------------------------
  2511                              <1> MD_TBL6:
  2512 000065CB AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2513 000065CC 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2514 000065CD 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2515 000065CE 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2516 000065CF 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2517 000065D0 1B                  <1> 	DB	01BH		; GAP LENGTH
  2518 000065D1 FF                  <1> 	DB	0FFH		; DTL
  2519 000065D2 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2520 000065D3 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2521 000065D4 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2522 000065D5 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2523 000065D6 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2524 000065D7 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2525                              <1> 
  2526                              <1> 
  2527                              <1> ; << diskette.inc >>
  2528                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2529                              <1> ;
  2530                              <1> ;----------------------------------------
  2531                              <1> ;	ROM BIOS DATA AREAS		:
  2532                              <1> ;----------------------------------------
  2533                              <1> 
  2534                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2535                              <1> 
  2536                              <1> ;----------------------------------------
  2537                              <1> ;	FIXED DISK DATA AREAS		:
  2538                              <1> ;----------------------------------------
  2539                              <1> 
  2540                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2541                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2542                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2543                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2544                              <1> 
  2545                              <1> ;----------------------------------------
  2546                              <1> ;	ADDITIONAL MEDIA DATA		:
  2547                              <1> ;----------------------------------------
  2548                              <1> 
  2549                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2550                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2551                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2552                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2553                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2554                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2555                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2556                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2557                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2558                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2559                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2560                              <1> 
  2561                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2562                              <1> ;
  2563                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2564                              <1> 
  2565                              <1> ERR_TBL:
  2566 000065D8 E0                  <1> 	db	NO_ERR
  2567 000065D9 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2568 000065DD 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2569                              <1> 
  2570                              <1> ; 17/12/2014 (mov ax, [cfd])
  2571                              <1> ; 11/12/2014
  2572 000065E1 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2573                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2574 000065E2 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2575                              <1> 					; (initial value of 'pfd 
  2576                              <1> 					; must be different then 'cfd' value
  2577                              <1> 					; to force updating/initializing
  2578                              <1> 					; current drive parameters) 
  2579 000065E3 90                  <1> align 2
  2580                              <1> 
  2581 000065E4 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2582                              <1> 			      ; (170h)
  2583 000065E6 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2584                              <1> 
  2585                              <1> ; 05/01/2015 
  2586 000065E8 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2587                              <1> 
  2588                              <1> ; *****************************************************************************
  2305                                  ;;;
  2306                                  
  2307 000065E9 90                      Align 2
  2308                                  
  2309                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2310 000065EA 00                      boot_drv:    db 0 ; boot drive number (physical)
  2311                                  ; 24/11/2014
  2312 000065EB 00                      drv:	     db 0 
  2313 000065EC 00                      last_drv:    db 0 ; last hdd
  2314 000065ED 00                      hdc:         db 0  ; number of hard disk drives
  2315                                  		     ; (present/detected)
  2316                                  ;
  2317                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2318                                  ; Physical drive type & flags
  2319 000065EE 00                      fd0_type:    db 0  ; floppy drive type
  2320 000065EF 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2321                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2322                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2323                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2324                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2325 000065F0 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2326 000065F1 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2327 000065F2 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2328 000065F3 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2329                                  		     ; bit 0 - Fixed disk access subset supported
  2330                                  		     ; bit 1 - Drive locking and ejecting
  2331                                  		     ; bit 2 - Enhanced disk drive support
  2332                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2333                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2334                                  		     ; will interpret it as 'LBA ready'!)		
  2335                                  
  2336                                  ; 11/03/2015 - 10/07/2015
  2337 000065F4 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2337 000065FD 0000000000         
  2338 00006602 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2338 0000660B 0000000000         
  2339 00006610 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2339 00006619 0000000000         
  2340 0000661E 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2340 00006627 000000000000000000-
  2340 00006630 000000000000000000-
  2340 00006639 00                 
  2341 0000663A 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2342 00006641 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2343                                  ;
  2344                                  
  2345                                  ; 27/08/2014
  2346                                  scr_row:
  2347 00006648 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2348                                  scr_col:
  2349 0000664C 00000000                	dd 0
  2350                                  
  2351                                  ;; 14/08/2015
  2352                                  ;;msgPM:
  2353                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2354                                  msgKVER:
  2355 00006650 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [26/02/2022]", 0
  2355 00006659 58203338362076312E-
  2355 00006662 31202D204B65726E65-
  2355 0000666B 6C2076302E322E312E-
  2355 00006674 32205B32362F30322F-
  2355 0000667D 323032325D00       
  2356                                  
  2357 00006683 90                      Align 2
  2358                                  
  2359                                  ; 20/08/2014
  2360                                    ; /* This is the default interrupt "handler" :-) */ 
  2361                                    ; Linux v0.12 (head.s)
  2362                                  int_msg:
  2363 00006684 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2363 0000668D 6E7465727275707420-
  2363 00006696 212000             
  2364                                  
  2365 00006699 90                      Align 2  
  2366                                  
  2367                                  ; 21/08/2014
  2368                                  timer_msg:
  2369 0000669A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2369 000066A3 542032306829202120-
  2369 000066AC 54696D657220496E74-
  2369 000066B5 657272757074203A20 
  2370                                  tcountstr:
  2371 000066BE 303030303020            	db "00000 "
  2372 000066C4 00                      	db 0
  2373                                  
  2374 000066C5 90                      Align 2
  2375                                  	; 21/08/2014
  2376                                  exc_msg:
  2377 000066C6 435055206578636570-     	db "CPU exception ! "
  2377 000066CF 74696F6E202120     
  2378                                  excnstr: 		; 25/08/2014
  2379 000066D6 3F3F68202045495020-     	db "??h", "  EIP : "
  2379 000066DF 3A20               
  2380                                  EIPstr: ; 29/08/2014
  2381 000066E1 00<rep Ch>              	times 12 db 0
  2382                                  rtc_msg:
  2383 000066ED 5265616C2054696D65-     	db "Real Time Clock - "
  2383 000066F6 20436C6F636B202D20 
  2384                                  datestr:
  2385 000066FF 30302F30302F303030-     	db "00/00/0000"
  2385 00006708 30                 
  2386 00006709 20                      	db " "
  2387                                  daystr:
  2388 0000670A 44415920                	db "DAY "
  2389                                  timestr:	
  2390 0000670E 30303A30303A3030                db "00:00:00"
  2391 00006716 20                      	db " "
  2392 00006717 00                      	db 0 
  2393                                  
  2394                                  daytmp:
  2395                                  	; 28/02/2015
  2396 00006718 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2396 00006721 4F4E20545545205745-
  2396 0000672A 442054485520465249-
  2396 00006733 2053415420         
  2397                                  
  2398 00006738 FF                      ptime_seconds: db 0FFh
  2399                                  
  2400                                  	; 23/02/2015
  2401                                  	; 25/08/2014
  2402                                  ;scounter:
  2403                                  ;	db 5
  2404                                  ;	db 19
  2405                                  
  2406                                  ; 02/01/2022
  2407                                  ; 05/11/2014
  2408                                  ;msg_out_of_memory:
  2409                                  ;	db 	07h, 0Dh, 0Ah
  2410                                  ;       db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2411                                  ; 	db	0Dh, 0Ah, 0
  2412                                  	;
  2413                                  setup_error_msg:
  2414 00006739 0D0A                    	db 0Dh, 0Ah
  2415 0000673B 4469736B2053657475-     	db 'Disk Setup Error!' 
  2415 00006744 70204572726F7221   
  2416 0000674C 0D0A00                  	db 0Dh, 0Ah,0
  2417                                  
  2418                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2419                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2420                                  ;	  db 0 ; upper left row (for scroll)	
  2421                                  
  2422                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2423                                  ;	  db 24 ; lower right row (for scroll)
  2424                                  
  2425                                  
  2426                                  ; 06/11/2014 (Temporary Data)
  2427                                  ; Memory Information message
  2428                                  ; 14/08/2015
  2429                                  msg_memory_info:
  2430 0000674F 07                      	db	07h
  2431 00006750 0D0A                    	db	0Dh, 0Ah
  2432                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2433 00006752 546F74616C206D656D-     	db	"Total memory : "
  2433 0000675B 6F7279203A20       
  2434                                  mem_total_b_str: ; 10 digits
  2435 00006761 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2435 0000676A 302062797465730D0A 
  2436 00006773 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2436 0000677C 202020202020202020 
  2437                                  mem_total_p_str: ; 7 digits
  2438 00006785 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2438 0000678E 616765730D0A       
  2439 00006794 0D0A                    	db 	0Dh, 0Ah
  2440 00006796 46726565206D656D6F-     	db	"Free memory  : "
  2440 0000679F 727920203A20       
  2441                                  free_mem_b_str:  ; 10 digits
  2442 000067A5 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2442 000067AE 3F2062797465730D0A 
  2443 000067B7 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2443 000067C0 202020202020202020 
  2444                                  free_mem_p_str:  ; 7 digits
  2445 000067C9 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2445 000067D2 616765730D0A       
  2446 000067D8 0D0A00                  	db	0Dh, 0Ah, 0
  2447                                  
  2448                                  dsk_ready_msg:
  2449 000067DB 0D0A                    	db 	0Dh, 0Ah
  2450                                  dsktype:
  2451 000067DD 6664                    	db	'fd'
  2452                                  dskx:
  2453 000067DF 30                      	db	'0'
  2454 000067E0 20                      	db	20h
  2455 000067E1 697320524541445920-     	db 	'is READY ...'
  2455 000067EA 2E2E2E             
  2456 000067ED 00                      	db 	0
  2457                                  nextline:
  2458 000067EE 0D0A00                  	db 	0Dh, 0Ah, 0
  2459                                  
  2460                                  ; KERNEL - SYSINIT Messages
  2461                                  ; 24/08/2015
  2462                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2463                                  ; 14/07/2013
  2464                                  ;kernel_init_err_msg:
  2465                                  ;	db 0Dh, 0Ah
  2466                                  ;	db 07h
  2467                                  ;	db 'Kernel initialization ERROR !'
  2468                                  ;	db 0Dh, 0Ah, 0 
  2469                                  ; 24/08/2015
  2470                                  ;;; (temporary kernel init message has been removed
  2471                                  ;;;  from 'sys_init' code)
  2472                                  ;kernel_init_ok_msg: 
  2473                                  ;	db 0Dh, 0Ah
  2474                                  ;	db 07h
  2475                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2476                                  ;	db 0Dh, 0Ah
  2477                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2478                                  ;	db 0Dh, 0Ah, 0
  2479                                  panic_msg:
  2480 000067F1 0D0A07                  	db 0Dh, 0Ah, 07h
  2481 000067F4 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2481 000067FD 726E656C2050616E69-
  2481 00006806 632021             
  2482 00006809 0D0A00                  	db 0Dh, 0Ah, 0
  2483                                  etc_init_err_msg:
  2484 0000680C 0D0A                    	db 0Dh, 0Ah
  2485 0000680E 07                      	db 07h
  2486 0000680F 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2486 00006818 74632F696E69742021-
  2486 00006821 3F                 
  2487 00006822 0D0A00                  	db 0Dh, 0Ah, 0
  2488                                  
  2489                                  ; 10/05/2015
  2490                                  badsys_msg:
  2491 00006825 0D0A                    	db 0Dh, 0Ah
  2492 00006827 07                      	db 07h
  2493 00006828 496E76616C69642053-     	db 'Invalid System Call !'
  2493 00006831 797374656D2043616C-
  2493 0000683A 6C2021             
  2494 0000683D 0D0A                    	db 0Dh, 0Ah
  2495 0000683F 4541583A20              	db 'EAX: '
  2496                                  bsys_msg_eax:
  2497 00006844 303030303030303068      	db '00000000h'
  2498 0000684D 0D0A                    	db 0Dh, 0Ah
  2499 0000684F 4549503A20              	db 'EIP: '
  2500                                  bsys_msg_eip:
  2501 00006854 303030303030303068      	db '00000000h' 
  2502 0000685D 0D0A00                  	db 0Dh, 0Ah, 0
  2503                                  
  2504                                  BSYS_M_SIZE equ $ - badsys_msg
  2505                                  
  2506                                  
  2507                                  align 2
  2508                                  
  2509                                  ; EPOCH Variables
  2510                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2511                                  ; 09/04/2013 epoch variables
  2512                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2513                                  ;
  2514 00006860 B207                    year: 	dw 1970
  2515 00006862 0100                    month: 	dw 1
  2516 00006864 0100                    day: 	dw 1
  2517 00006866 0000                    hour: 	dw 0
  2518 00006868 0000                    minute: dw 0
  2519 0000686A 0000                    second: dw 0
  2520                                  
  2521                                  DMonth:
  2522 0000686C 0000                    	dw 0
  2523 0000686E 1F00                    	dw 31
  2524 00006870 3B00                    	dw 59
  2525 00006872 5A00                    	dw 90
  2526 00006874 7800                    	dw 120
  2527 00006876 9700                    	dw 151
  2528 00006878 B500                    	dw 181
  2529 0000687A D400                    	dw 212
  2530 0000687C F300                    	dw 243
  2531 0000687E 1101                    	dw 273
  2532 00006880 3001                    	dw 304
  2533 00006882 4E01                    	dw 334
  2534                                  
  2535                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
  2536                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2537 00006884 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2538                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2539 00006886 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2540 00006888 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2541                                  		   ;   between 16 MB and 4 GB.
  2542 0000688A 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2543                                  
  2544                                  ; 02/01/2022
  2545                                  KEND:
  2546                                  
  2547 0000688C 90<rep 4h>              align 16
  2548                                  
  2549                                  bss_start:
  2550                                  
  2551                                  ABSOLUTE bss_start
  2552                                  
  2553                                  	; 11/03/2015
  2554                                  	; Interrupt Descriptor Table (20/08/2014)
  2555                                  idt:
  2556 00006890 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2557                                  idt_end:
  2558                                  
  2559                                  ;alignb 4
  2560                                  
  2561                                  task_state_segment:
  2562                                  	; 24/03/2015
  2563 00006A90 ????                    tss.link:   resw 1
  2564 00006A92 ????                    	    resw 1
  2565                                  ; tss offset 4	
  2566 00006A94 ????????                tss.esp0:   resd 1
  2567 00006A98 ????                    tss.ss0:    resw 1
  2568 00006A9A ????                    	    resw 1	
  2569 00006A9C ????????                tss.esp1:   resd 1
  2570 00006AA0 ????                    tss.ss1:    resw 1
  2571 00006AA2 ????                    	    resw 1 	
  2572 00006AA4 ????????                tss.esp2:   resd 1
  2573 00006AA8 ????                    tss.ss2:    resw 1
  2574 00006AAA ????                    	    resw 1
  2575                                  ; tss offset 28
  2576 00006AAC ????????                tss.CR3:    resd 1
  2577 00006AB0 ????????                tss.eip:    resd 1
  2578 00006AB4 ????????                tss.eflags: resd 1
  2579                                  ; tss offset 40
  2580 00006AB8 ????????                tss.eax:    resd 1		 		
  2581 00006ABC ????????                tss.ecx:    resd 1
  2582 00006AC0 ????????                tss.edx:    resd 1
  2583 00006AC4 ????????                tss.ebx:    resd 1
  2584 00006AC8 ????????                tss.esp:    resd 1
  2585 00006ACC ????????                tss.ebp:    resd 1
  2586 00006AD0 ????????                tss.esi:    resd 1
  2587 00006AD4 ????????                tss.edi:    resd 1
  2588                                  ; tss offset 72
  2589 00006AD8 ????                    tss.ES:     resw 1
  2590 00006ADA ????                    	    resw 1	
  2591 00006ADC ????                    tss.CS:	    resw 1
  2592 00006ADE ????                    	    resw 1
  2593 00006AE0 ????                    tss.SS:	    resw 1
  2594 00006AE2 ????                    	    resw 1
  2595 00006AE4 ????                    tss.DS:	    resw 1
  2596 00006AE6 ????                    	    resw 1
  2597 00006AE8 ????                    tss.FS:	    resw 1
  2598 00006AEA ????                    	    resw 1
  2599 00006AEC ????                    tss.GS:	    resw 1
  2600 00006AEE ????                    	    resw 1		
  2601 00006AF0 ????                    tss.LDTR:   resw 1
  2602 00006AF2 ????                    	    resw 1
  2603                                  ; tss offset 100		
  2604 00006AF4 ????                    	    resw 1		
  2605 00006AF6 ????                    tss.IOPB:   resw 1
  2606                                  ; tss offset 104 
  2607                                  tss_end:
  2608                                  
  2609 00006AF8 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2610                                  		  ;   (Physical address = Virtual address)	 	
  2611 00006AFC ????????                memory_size: resd 1 ; memory size in pages
  2612 00006B00 ????????                free_pages:  resd 1 ; number of free pages		
  2613 00006B04 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2614                                  		  ;   first free page search
  2615 00006B08 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2616                                  		  ;   next free page search will be
  2617                                  		  ; stopped after it. (end of M.A.T.)
  2618 00006B0C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2619                                  		  ; first free page search
  2620                                  		  ;   will be started on it. (for user)
  2621 00006B10 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2622                                  
  2623                                  ;;;
  2624                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2625                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2626 00006B14 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2627                                  			  ; NOTE: active page only
  2628 00006B16 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2629                                  active_page: 
  2630 00006B26 ??                      ptty: 	     resb 1 	  ; current tty
  2631                                  ; 01/07/2015
  2632 00006B27 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2633                                  ; 26/10/2015
  2634                                  ; 07/09/2014
  2635 00006B28 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2636                                  
  2637                                  ; 21/08/2014
  2638 00006B3C ????????                tcount:	     resd 1
  2639                                  
  2640                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2641 00006B40 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2642                                  
  2643                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2644                                  ; (open mode locks for pseudo TTYs)
  2645                                  ; [ major tty locks (return error in any conflicts) ]
  2646 00006B44 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2647                                  
  2648                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2649                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2650 00006B58 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2651                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2652                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2653                                  ;; 0 means serial port is not available 
  2654                                  ;;comprm: ; 25/06/2014
  2655 00006B62 ??                      com1p:       resb 1  ;;0E3h
  2656 00006B63 ??                      com2p:       resb 1  ;;0E3h
  2657                                  
  2658                                  ; 17/11/2015
  2659                                  ; request for response (from the terminal)	
  2660 00006B64 ????                    req_resp:     resw 1 			
  2661                                  ; 07/11/2015
  2662 00006B66 ??                      ccomport:    resb 1 ; current COM (serial) port
  2663                                  		    ; (0= COM1, 1= COM2)
  2664                                  ; 09/11/2015
  2665 00006B67 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2666                                  ; 07/11/2015
  2667 00006B68 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2668 00006B6A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2669                                  
  2670                                  ; 23/10/2015
  2671                                  ; SERIAL PORTS - COMMUNICATION MODES
  2672                                  ; (Retro UNIX 386 v1 feature only!)
  2673                                  ; 0 - command mode (default/initial mode)
  2674                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2675                                  ;;; communication modes for futre versions:  
  2676                                  ; // 2 - keyboard mode (ascii+scancode input)
  2677                                  ; // 3 - mouse mode
  2678                                  ; // 4 - device control (output) mode
  2679                                  ; VALID COMMANDS for current version:
  2680                                  ; 	'LOGIN'
  2681                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2682                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2683                                  ;  Login response: db 0FFh, 'login', 0
  2684                                  ;	 ("login request accepted, wait for login prompt") 
  2685                                  ; When a login requests is received and acknowledged (by
  2686                                  ; serial port interrupt handler (communication procedure),
  2687                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2688                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2689                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2690                                  ; 
  2691                                  ; 'sys connect' system call is used to change communication mode
  2692                                  ; except 'LOGIN' command which is used to start terminal mode
  2693                                  ; by using (COM port) terminal.
  2694                                  
  2695                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2696                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2697                                  ;com1mode:    resb 1 ; communication mode for COM1
  2698                                  ;com1com:     resb 1 ; communication command for COM1
  2699                                  ;com2mode:    resb 1 ; communication mode for COM1
  2700                                  ;com2com      resb 1 ; communication command for COM1
  2701                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2702                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2703                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2704                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2705                                  
  2706                                  ; 22/08/2014 (RTC)
  2707                                  ; (Packed BCD)
  2708 00006B6C ??                      time_seconds: resb 1
  2709 00006B6D ??                      time_minutes: resb 1
  2710 00006B6E ??                      time_hours:   resb 1
  2711 00006B6F ??                      date_wday:    resb 1
  2712 00006B70 ??                      date_day:     resb 1
  2713 00006B71 ??                      date_month:   resb 1			
  2714 00006B72 ??                      date_year:    resb 1
  2715 00006B73 ??                      date_century: resb 1
  2716                                  
  2717                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2718                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2719                              <1> ; Last Modification: 10/07/2015
  2720                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2721                              <1> ;
  2722                              <1> ; *****************************************************************************
  2723                              <1> 
  2724                              <1> alignb 2
  2725                              <1> 
  2726                              <1> ;----------------------------------------
  2727                              <1> ;	TIMER DATA AREA 		:
  2728                              <1> ;----------------------------------------
  2729                              <1> 
  2730                              <1> TIMER_LH:	; 16/02/205
  2731 00006B74 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2732 00006B76 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2733 00006B78 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2734                              <1> 
  2735                              <1> ;----------------------------------------
  2736                              <1> ;	DISKETTE DATA AREAS		:
  2737                              <1> ;----------------------------------------
  2738                              <1> 
  2739 00006B79 ??                  <1> SEEK_STATUS:	resb	1
  2740 00006B7A ??                  <1> MOTOR_STATUS:	resb	1
  2741 00006B7B ??                  <1> MOTOR_COUNT:	resb	1
  2742 00006B7C ??                  <1> DSKETTE_STATUS:	resb	1
  2743 00006B7D ??????????????      <1> NEC_STATUS:	resb	7
  2744                              <1> 
  2745                              <1> ;----------------------------------------
  2746                              <1> ;	ADDITIONAL MEDIA DATA		:
  2747                              <1> ;----------------------------------------
  2748                              <1> 
  2749 00006B84 ??                  <1> LASTRATE:	resb 	1
  2750 00006B85 ??                  <1> HF_STATUS:	resb 	1
  2751 00006B86 ??                  <1> HF_ERROR:	resb 	1
  2752 00006B87 ??                  <1> HF_INT_FLAG:	resb 	1
  2753 00006B88 ??                  <1> HF_CNTRL:	resb 	1
  2754 00006B89 ????????            <1> DSK_STATE:	resb 	4
  2755 00006B8D ????                <1> DSK_TRK:	resb 	2
  2756                              <1> 
  2757                              <1> ;----------------------------------------
  2758                              <1> ;	FIXED DISK DATA AREAS		:
  2759                              <1> ;----------------------------------------
  2760                              <1> 
  2761 00006B8F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2762 00006B90 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2763 00006B91 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2764                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2765                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2766                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2767                              <1> 
  2768 00006B92 ????                <1> alignb 4
  2769                              <1> 
  2770                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2771                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2772                              <1> HF_TBL_VEC: ; 22/12/2014	
  2773 00006B94 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2774 00006B98 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2775 00006B9C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2776 00006BA0 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2777                              <1> 
  2778                              <1> ; 03/01/2015
  2779 00006BA4 ??                  <1> LBAMode:     	resb	1
  2780                              <1> 
  2781                              <1> ; *****************************************************************************
  2718                                  
  2719                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2720                                  
  2721                                  ;alignb 2
  2722                                  
  2723                                  ; 02/01/2022
  2724                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2725                                  
  2726                                  ; 24/12/2021
  2727                                  ; (memory page swap parameters are disabled as temporary)
  2728                                  ;
  2729                                  ;; Memory (swap) Data (11/03/2015)
  2730                                  ; 09/03/2015
  2731                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2732                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2733                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2734                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2735                                  ;swpd_next:  resd 1 ; next free page block
  2736                                  ;swpd_last:  resd 1 ; last swap page block	
  2737                                  	
  2738 00006BA5 ??????                  alignb 4
  2739                                  
  2740                                  ; 10/07/2015
  2741                                  ; 28/08/2014
  2742 00006BA8 ????????                error_code:	resd 1
  2743                                  ; 29/08/2014
  2744 00006BAC ????????                FaultOffset: 	resd 1
  2745                                  ; 21/09/2015
  2746 00006BB0 ????????                PF_Count:	resd 1	; total page fault count
  2747                                  		       	; (for debugging - page fault analyze)
  2748                                  		 	; 'page _fault_handler' (memory.inc)
  2749                                  			; 'sysgeterr' (u9.s)
  2750                                  ; 26/02/2022
  2751 00006BB4 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2752                                  			;  for a system call in next retro unix 386 version)
  2753                                  			; -2 ticks per second-
  2754                                  ;; 21/08/2015
  2755                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2756                                  
  2757                                  ; 02/01/2022
  2758                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2759                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYSX.INC (ux.s)
  2760                              <1> ; Last Modification: 26/02/2022
  2761                              <1> ; ----------------------------------------------------------------------------
  2762                              <1> ; Retro UNIX 386 v1 Kernel - ux.s
  2763                              <1> ; Last Modification: 04/12/2015
  2764                              <1> ;
  2765                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2766                              <1> ; (Modified from 
  2767                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2768                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2769                              <1> ; ----------------------------------------------------------------------------
  2770                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2771                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2772                              <1> ; <Bell Laboratories (17/3/1972)>
  2773                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2774                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2775                              <1> ; ****************************************************************************
  2776                              <1> 
  2777                              <1> alignb 2
  2778                              <1> 
  2779                              <1> inode:
  2780                              <1> 	; 11/03/2013. 
  2781                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2782                              <1> 	;i.
  2783                              <1> 
  2784 00006BB8 ????                <1> 	i.flgs:	 resw 1
  2785 00006BBA ??                  <1> 	i.nlks:	 resb 1
  2786 00006BBB ??                  <1> 	i.uid:	 resb 1
  2787 00006BBC ????                <1>         i.size:  resw 1 ; size
  2788 00006BBE <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2789 00006BCE ????????            <1> 	i.ctim:	 resd 1
  2790 00006BD2 ????????            <1> 	i.mtim:	 resd 1
  2791 00006BD6 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2792                              <1> 
  2793                              <1> I_SIZE	equ $ - inode 
  2794                              <1> 
  2795                              <1> process:
  2796                              <1> 	; 26/02/2022
  2797                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1) 
  2798                              <1> 	; 06/05/2015
  2799                              <1> 	; 11/03/2013 - 05/02/2014
  2800                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2801                              <1> 	;p.
  2802                              <1> 	
  2803 00006BD8 <res 20h>           <1>         p.pid:   resw nproc
  2804 00006BF8 <res 20h>           <1>         p.ppid:  resw nproc
  2805                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2806 00006C18 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2807                              <1> 	; 26/02/2022 (p.waitc is not used)
  2808                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2809 00006C28 <res 10h>           <1> 	p.link:	 resb nproc
  2810 00006C38 <res 10h>           <1> 	p.stat:	 resb nproc
  2811                              <1> 
  2812                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2813 00006C48 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2814                              <1> 			    ; 'user' structure	
  2815                              <1> 
  2816                              <1> P_SIZE	equ $ - process
  2817                              <1> 
  2818                              <1> ; fsp table (original UNIX v1)
  2819                              <1> ;
  2820                              <1> ;Entry
  2821                              <1> ;          15                                      0
  2822                              <1> ;  1     |---|---------------------------------------|
  2823                              <1> ;        |r/w|       i-number of open file           |
  2824                              <1> ;        |---|---------------------------------------| 
  2825                              <1> ;        |               device number               |
  2826                              <1> ;        |-------------------------------------------|
  2827                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2828                              <1> ;        |-------------------------------------------| 
  2829                              <1> ;        |  flag that says    | number of processes  |
  2830                              <1> ;        |   file deleted     | that have file open  |
  2831                              <1> ;        |-------------------------------------------| 
  2832                              <1> ;  2     |                                           |
  2833                              <1> ;        |-------------------------------------------| 
  2834                              <1> ;        |                                           |
  2835                              <1> ;        |-------------------------------------------|
  2836                              <1> ;        |                                           |
  2837                              <1> ;        |-------------------------------------------|
  2838                              <1> ;        |                                           |
  2839                              <1> ;        |-------------------------------------------| 
  2840                              <1> ;  3     |                                           | 
  2841                              <1> ;        |                                           |  
  2842                              <1> ;
  2843                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2844                              <1> 
  2845                              <1> ; 15/04/2015
  2846 00006C88 <res 1F4h>          <1> fsp:	 resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2847 00006E7C <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2848 00006E9C ????                <1> ii:	 resw 1
  2849                              <1> ;idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2850                              <1> ;cdev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2851                              <1> ; 11/01/2022
  2852 00006E9E ??                  <1> idev:	 resb 1
  2853 00006E9F ??                  <1> cdev:	 resb 1
  2854                              <1> ; 18/05/2015
  2855                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2856                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2857                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2858                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2859                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2860                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2861                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2862                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2863                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2864                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2865                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2866 00006EA0 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2867                              <1> 	        ; as above, for physical drives numbers in following table
  2868 00006EA1 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2869                              <1> ; 15/04/2015
  2870 00006EA2 ??                  <1> active:	 resb 1 
  2871 00006EA3 ??                  <1> 	 resb 1 ; 09/06/2015
  2872 00006EA4 ????                <1> mnti:	 resw 1
  2873 00006EA6 ????                <1> mpid:	 resw 1
  2874 00006EA8 ????                <1> rootdir: resw 1
  2875                              <1> ; 14/02/2014
  2876                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2877                              <1> ;		      Single level run queue
  2878                              <1> ;		      (in order to solve sleep/wakeup lock)
  2879 00006EAA ????                <1> runq:	 resw 1
  2880 00006EAC ??                  <1> imod:	 resb 1
  2881 00006EAD ??                  <1> smod:	 resb 1
  2882 00006EAE ??                  <1> mmod:	 resb 1
  2883 00006EAF ??                  <1> sysflg:	 resb 1
  2884                              <1> 
  2885                              <1> alignb 4
  2886                              <1> 
  2887                              <1> user:
  2888                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2889                              <1> 	; 04/12/2015 
  2890                              <1> 	; 18/10/2015
  2891                              <1> 	; 12/10/2015
  2892                              <1> 	; 21/09/2015
  2893                              <1> 	; 24/07/2015
  2894                              <1> 	; 16/06/2015
  2895                              <1> 	; 09/06/2015
  2896                              <1> 	; 11/05/2015
  2897                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2898                              <1> 	; 10/10/2013
  2899                              <1> 	; 11/03/2013. 
  2900                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2901                              <1> 	;u.
  2902                              <1> 
  2903 00006EB0 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2904 00006EB4 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2905 00006EB8 ????????            <1> 	u.r0:	  resd 1 ; eax
  2906 00006EBC ????                <1> 	u.cdir:	  resw 1
  2907 00006EBE <res Ah>            <1> 	u.fp:	  resb 10
  2908 00006EC8 ????????            <1> 	u.fofp:	  resd 1
  2909 00006ECC ????????            <1> 	u.dirp:	  resd 1
  2910 00006ED0 ????????            <1> 	u.namep:  resd 1
  2911 00006ED4 ????????            <1> 	u.off:	  resd 1
  2912 00006ED8 ????????            <1> 	u.base:	  resd 1
  2913 00006EDC ????????            <1> 	u.count:  resd 1
  2914 00006EE0 ????????            <1> 	u.nread:  resd 1
  2915 00006EE4 ????????            <1> 	u.break:  resd 1 ; break
  2916 00006EE8 ????                <1> 	u.ttyp:	  resw 1 
  2917 00006EEA <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2918                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2919 00006EFA ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2920 00006EFB ??                  <1> 	u.pri:	  resb 1 ; 
  2921 00006EFC ????                <1> 	u.intr:	  resw 1
  2922 00006EFE ????                <1> 	u.quit:	  resw 1
  2923                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2924 00006F00 ????                <1> 	u.ilgins: resw 1
  2925                              <1> 	;u.cdrv:  resw 1 ; cdev
  2926 00006F02 ??                  <1> 	u.cdrv:   resb 1 ; 09/01/2022
  2927 00006F03 ??                  <1> 		  resb 1 ; 09/01/2022 (dword alignment)
  2928 00006F04 ??                  <1> 	u.uid:	  resb 1 ; uid
  2929 00006F05 ??                  <1> 	u.ruid:	  resb 1
  2930 00006F06 ??                  <1> 	u.bsys:	  resb 1
  2931 00006F07 ??                  <1> 	u.uno:	  resb 1
  2932 00006F08 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2933                              <1> 	; tty number (rtty, rcvt, wtty)
  2934 00006F0C ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2935                              <1> 	; last error number
  2936 00006F0D ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2937                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2938 00006F11 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2939 00006F15 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2940 00006F19 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2941 00006F1D ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2942                              <1> 	;u.pncount: resw 1 
  2943                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2944                              <1> 	;u.pnbase:  resd 1 
  2945                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2946                              <1> 			 ; 09/06/2015
  2947 00006F1F ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2948 00006F20 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2949                              <1> 			 ; 24/07/2015 - 24/06/2015
  2950                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2951                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2952                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2953                              <1>  			 ; 24/06/2015	  	
  2954                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2955                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2956                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2957 00006F21 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2958                              <1> 
  2959 00006F25 ??????              <1> alignb 4
  2960                              <1> 
  2961                              <1> U_SIZE	equ $ - user
  2962                              <1> 
  2963                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2964 00006F28 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2965 00006F2C ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2966 00006F30 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2967 00006F34 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2968                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  2969 00006F36 ??                  <1> argc:	resb 1	; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2970 00006F37 ??                  <1> 	resb 1 
  2971 00006F38 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2972                              <1> 
  2973                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2974                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2975 00006F3C ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2976 00006F3D ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2977 00006F3E ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2978 00006F3F ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2979                              <1> 
  2980                              <1> ;alignb 4
  2981                              <1> 
  2982                              <1> ; 22/08/2015
  2983 00006F40 <res C30h>          <1> buffer: resb nbuf * 520
  2984                              <1> 
  2985 00007B70 ????????????????    <1> sb0:	resd 2
  2986                              <1> ;s:
  2987                              <1> ; (root disk) super block buffer
  2988                              <1> systm:
  2989                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2990                              <1> 	; 11/03/2013. 
  2991                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2992                              <1> 	;s.
  2993                              <1> 
  2994 00007B78 ????                <1> 	resw 1
  2995 00007B7A <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2996 00007CE2 ????                <1> 	resw 1
  2997 00007CE4 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2998                              <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table)
  2999 00007D04 ????????            <1> 	s.time:	 resd 1
  3000 00007D08 ????????            <1> 	s.syst:	 resd 1
  3001 00007D0C ????????            <1>         s.wait_: resd 1 ; wait
  3002 00007D10 ????????            <1> 	s.idlet: resd 1
  3003 00007D14 ????????            <1> 	s.chrgt: resd 1
  3004 00007D18 ????                <1> 	s.drerr: resw 1
  3005                              <1> 
  3006                              <1> S_SIZE	equ $ - systm
  3007                              <1> 
  3008 00007D1A <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  3009                              <1> 
  3010 00007D78 ????????????????    <1> sb1:	resd 2
  3011                              <1> ; (mounted disk) super block buffer
  3012                              <1> mount:	
  3013 00007D80 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3014                              <1> 
  3015                              <1> ;/ ux -- unix
  3016                              <1> ;
  3017                              <1> ;systm:
  3018                              <1> ;
  3019                              <1> ;	.=.+2
  3020                              <1> ;	.=.+128.
  3021                              <1> ;	.=.+2
  3022                              <1> ;	.=.+64.
  3023                              <1> ;	s.time: .=.+4
  3024                              <1> ;	s.syst: .=.+4
  3025                              <1> ;	s.wait: .=.+4
  3026                              <1> ;	s.idlet:.=.+4
  3027                              <1> ;	s.chrgt:.=.+4
  3028                              <1> ;	s.drerr:.=.+2
  3029                              <1> ;inode:
  3030                              <1> ;	i.flgs: .=.+2
  3031                              <1> ;	i.nlks: .=.+1
  3032                              <1> ;	i.uid:  .=.+1
  3033                              <1> ;	i.size: .=.+2
  3034                              <1> ;	i.dskp: .=.+16.
  3035                              <1> ;	i.ctim: .=.+4
  3036                              <1> ;	i.mtim: .=.+4
  3037                              <1> ;	. = inode+32.
  3038                              <1> ;mount:	.=.+1024.
  3039                              <1> ;proc:
  3040                              <1> ;	p.pid:  .=.+[2*nproc]
  3041                              <1> ;	p.dska: .=.+[2*nproc]
  3042                              <1> ;	p.ppid: .=.+[2*nproc]
  3043                              <1> ;	p.break:.=.+[2*nproc]
  3044                              <1> ;	p.link: .=.+nproc
  3045                              <1> ;	p.stat: .=.+nproc
  3046                              <1> ;tty:
  3047                              <1> ;	. = .+[ntty*8.]
  3048                              <1> ;fsp:	.=.+[nfiles*8.]
  3049                              <1> ;bufp:	.=.+[nbuf*2]+6
  3050                              <1> ;sb0:	.=.+8
  3051                              <1> ;sb1:	.=.+8
  3052                              <1> ;swp:	.=.+8
  3053                              <1> ;ii:	.=.+2
  3054                              <1> ;idev:	.=.+2
  3055                              <1> ;cdev:	.=.+2
  3056                              <1> ;deverr: .=.+12.
  3057                              <1> ;active: .=.+2
  3058                              <1> ;rfap:	.=.+2
  3059                              <1> ;rkap:	.=.+2
  3060                              <1> ;tcap:	.=.+2
  3061                              <1> ;tcstate:.=.+2
  3062                              <1> ;tcerrc: .=.+2
  3063                              <1> ;mnti:	.=.+2
  3064                              <1> ;mntd:	.=.+2
  3065                              <1> ;mpid:	.=.+2
  3066                              <1> ;clockp: .=.+2
  3067                              <1> ;rootdir:.=.+2
  3068                              <1> ;toutt:	.=.+16.
  3069                              <1> ;touts: .=.+32.
  3070                              <1> ;runq:	.=.+6
  3071                              <1> ;
  3072                              <1> ;wlist:	.=.+40.
  3073                              <1> ;cc:	.=.+30.
  3074                              <1> ;cf:	.=.+31.
  3075                              <1> ;cl:	.=.+31.
  3076                              <1> ;clist:	.=.+510.
  3077                              <1> ;imod:	.=.+1
  3078                              <1> ;smod:	.=.+1
  3079                              <1> ;mmod:	.=.+1
  3080                              <1> ;uquant: .=.+1
  3081                              <1> ;sysflg: .=.+1
  3082                              <1> ;pptiflg:.=.+1
  3083                              <1> ;ttyoch: .=.+1
  3084                              <1> ; .even
  3085                              <1> ; .=.+100.; sstack:
  3086                              <1> ;buffer: .=.+[ntty*140.]
  3087                              <1> ;	.=.+[nbuf*520.]
  3088                              <1> ;
  3089                              <1> ; . = core-64.
  3090                              <1> ;user:
  3091                              <1> ;	u.sp:    .=.+2
  3092                              <1> ;	u.usp:   .=.+2
  3093                              <1> ;	u.r0:    .=.+2
  3094                              <1> ;	u.cdir:  .=.+2
  3095                              <1> ;	u.fp:    .=.+10.
  3096                              <1> ;	u.fofp:  .=.+2
  3097                              <1> ;	u.dirp:  .=.+2
  3098                              <1> ;	u.namep: .=.+2
  3099                              <1> ;	u.off:   .=.+2
  3100                              <1> ;	u.base:  .=.+2
  3101                              <1> ;	u.count: .=.+2
  3102                              <1> ;	u.nread: .=.+2
  3103                              <1> ;	u.break: .=.+2
  3104                              <1> ;	u.ttyp:  .=.+2
  3105                              <1> ;	u.dirbuf:.=.+10.
  3106                              <1> ;	u.pri:   .=.+2
  3107                              <1> ;	u.intr:  .=.+2
  3108                              <1> ;	u.quit:  .=.+2
  3109                              <1> ;	u.emt:   .=.+2
  3110                              <1> ;	u.ilgins:.=.+2
  3111                              <1> ;	u.cdev:  .=.+2
  3112                              <1> ;	u.uid:   .=.+1
  3113                              <1> ;	u.ruid:  .=.+1
  3114                              <1> ;	u.bsys:  .=.+1
  3115                              <1> ;	u.uno:   .=.+1
  3116                              <1> ;. = core
  2759                                  
  2760                                  ; 27/12/2021
  2761                                  ;buffer: resb (nbuf*520)
  2762                                  
  2763                                  bss_end:
  2764                                  
  2765                                  ; 02/01/2022
  2766                                  BSS_SIZE equ bss_end - bss_start
  2767                                  
  2768                                  ; 27/12/2013
  2769                                  _end:  ; end of kernel code (and read only data, just before bss)
