     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.1
     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                                  ;
    15                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    16                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    17                                  ; <Bell Laboratories (17/3/1972)>
    18                                  ; <Preliminary Release of UNIX Implementation Document>
    19                                  ;
    20                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    21                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    22                                  ;
    23                                  ; ****************************************************************************
    24                                  ; 31/12/2021
    25                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    26                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    27                                  
    28                                  ; 24/12/2021 - BugFix and Code Optimization
    29                                  ; Runix Kernel v0.2.1.1 
    30                                  
    31                                  ; 24/12/2013
    32                                  
    33                                  ; Entering protected mode:
    34                                  ; Derived from 'simple_asm.txt' source code file and 
    35                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    36                                  ; (gregor.brunmar@home.se)
    37                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    38                                  ;
    39                                  
    40                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    41                                  ; by Michael Chourdakis (2009) 
    42                                  ; http://www.codeproject.com/Articles/45788/
    43                                  ; http://www.michaelchourdakis.com
    44                                  ;
    45                                  
    46                                  ; Global Descriptor Table:
    47                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    48                                  ; by Linus Torvalds (1991-1992)
    49                                  ;
    50                                  
    51                                  KLOAD	equ 10000h ; Kernel loading address
    52                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    53                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    54                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    55                                  ; 19/03/2015
    56                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    57                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    58                                  ; 24/03/2015
    59                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    60                                  ; 19/03/2015
    61                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    62                                  		     ; (at the end of the 1st 4MB)
    63                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    64                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    65                                  
    66                                  ; 27/12/2013
    67                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    68                                  
    69                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    70                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    71                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    72                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    73                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    74                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    75                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    76                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    77                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    78                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    79                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    80                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    81                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    82                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    83                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    84                                  ;----------------------------------------
    85                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    86                                  ;-----------------------------------------------------------------------------
    87                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    88                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    89                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    90                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    91                                  
    92                                  ; Memory Allocation Table Address
    93                                  ; 05/11/2014
    94                                  ; 31/10/2014
    95                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    96                                  					; the 1st 1 MB memory space.
    97                                  					; (This address must be aligned
    98                                  					;  on 128 KB boundary, if it will be
    99                                  					;  changed later.)
   100                                  					; ((lower 17 bits of 32 bit M.A.T.
   101                                  					;   address must be ZERO)).
   102                                  					; ((((Reason: 32 bit allocation 
   103                                  					;     instructions, dword steps)))
   104                                  					; (((byte >> 12 --> page >> 5)))  
   105                                  ;04/11/2014	
   106                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   107                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   108                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   109                                  ;
   110                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   111                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   112                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   113                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   114                                  
   115                                  ; 17/02/2015 (unix386.s)
   116                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   117                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   118                                  ;
   119                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   120                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   121                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   122                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   123                                  
   124                                  
   125                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   126                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   127                                  ;
   128                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   129                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   130                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   131                                  		      ; otherwise it is standard FDPT with physical values 	
   132                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   133                                  		      ; (obsolete for IDE/ATA drives)
   134                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   135                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   136                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   137                                  			; Bit 4 : Reserved. Always 0
   138                                  			; Bit 3 : Set to 1 if more than 8 heads
   139                                  			; Bit 2-0 : Reserved. Alsways 0
   140                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   141                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   142                                  
   143                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   144                                  ; (11 bytes long) will be used by diskette handler/bios
   145                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   146                                  
   147                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   148                                  
   149                                  [ORG 0] 
   150                                  	; 12/11/2014
   151                                  	; Save boot drive number (that is default root drive)
   152 00000000 8816[DA66]              	mov	[boot_drv], dl ; physical drv number
   153                                  
   154                                  	; Determine installed memory
   155                                  	; 31/10/2014
   156                                  	;
   157 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   158 00000007 CD15                    	int	15h	   ; for large configurations
   159 00000009 7308                    	jnc	short chk_ms
   160 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   161 0000000D CD15                    	int	15h
   162                                  	;	   
   163                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   164                                  	;out	70h, al ; select CMOS register
   165                                  	;in	al, 71h ; read data (1 byte)
   166                                  	;mov	cl, al
   167                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   168                                  	;out	70h, al ; select CMOS register
   169                                  	;in	al, 71h ; read data (1 byte)
   170                                  	;mov	ch, al
   171                                   	;      
   172 0000000F 89C1                    	mov	cx, ax
   173 00000011 31D2                    	xor	dx, dx
   174                                  chk_ms:
   175 00000013 890E[B069]              	mov	[mem_1m_1k], cx
   176 00000017 8916[B269]              	mov	[mem_16m_64k], dx
   177                                  	; 05/11/2014
   178                                  	;and	dx, dx
   179                                  	;jz	short L2
   180 0000001B 81F90004                        cmp     cx, 1024
   181 0000001F 7315                    	jnb	short L0
   182                                  		 ; insufficient memory_error	
   183                                  		 ; Minimum 2 MB memory is needed... 
   184                                  	; 05/11/2014
   185                                  	; (real mode error printing)
   186 00000021 FB                      	sti
   187 00000022 BE[2968]                	mov	si, msg_out_of_memory
   188 00000025 BB0700                  	mov	bx, 7
   189 00000028 B40E                    	mov	ah, 0Eh	; write tty
   190                                  oom_1:
   191 0000002A AC                      	lodsb
   192 0000002B 08C0                    	or	al, al
   193 0000002D 7404                    	jz	short oom_2
   194 0000002F CD10                    	int	10h
   195 00000031 EBF7                    	jmp	short oom_1
   196                                  oom_2:
   197 00000033 F4                              hlt
   198 00000034 EBFD                    	jmp	short oom_2
   199                                  
   200                                  L0:
   201                                  %include 'diskinit.inc' ; 07/03/2015
   202                              <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC
   203                              <1> ; Last Modification: 04/02/2016
   204                              <1> 
   205                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   206                              <1> 
   207                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   208                              <1> 
   209                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   210                              <1> ;L0:
   211                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   212                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   213 00000036 BA7F00              <1> 	mov	dx, 7Fh
   214                              <1> L1:	
   215 00000039 FEC2                <1> 	inc	dl
   216 0000003B B441                <1> 	mov	ah, 41h ; Check extensions present
   217                              <1> 			; Phoenix EDD v1.1 - EDD v3
   218 0000003D BBAA55              <1> 	mov	bx, 55AAh
   219 00000040 CD13                <1> 	int 	13h
   220 00000042 721A                <1> 	jc	short L2
   221                              <1> 
   222 00000044 81FB55AA            <1> 	cmp	bx, 0AA55h
   223 00000048 7514                <1> 	jne	short L2
   224 0000004A FE06[DD66]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   225 0000004E 8816[DC66]          <1>         mov     [last_drv], dl  ; last hard disk number
   226 00000052 BB[6066]            <1> 	mov	bx, hd0_type - 80h
   227 00000055 01D3                <1> 	add	bx, dx	 
   228 00000057 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   229                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   230                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   231                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   232                              <1>                          ;            (EDD) ready (DPTE ready)
   233                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   234                              <1>                          ;            (EDD-3)
   235                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   236 00000059 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   237 0000005C 72DB                <1> 	jb	short L1
   238                              <1> L2:
   239                              <1> 	; 23/11/2014
   240                              <1> 	; 19/11/2014
   241 0000005E 30D2                <1> 	xor	dl, dl  ; 0
   242                              <1> 	; 04/02/2016 (esi -> si)
   243 00000060 BE[DE66]            <1> 	mov	si, fd0_type
   244                              <1> L3:
   245                              <1> 	; 14/01/2015
   246 00000063 8816[DB66]          <1> 	mov	[drv], dl
   247                              <1> 	;
   248 00000067 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   249 00000069 CD13                <1> 	int	13h	
   250 0000006B 7210                <1> 	jc	short L4
   251                              <1> 		; BL = drive type (for floppy drives)
   252                              <1> 		; DL = number of floppy drives
   253                              <1> 		;		
   254                              <1> 		; ES:DI = Address of DPT from BIOS
   255                              <1> 		;
   256 0000006D 881C                <1> 	mov	[si], bl ;  Drive type
   257                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   258                              <1> 	; 14/01/2015
   259 0000006F E8A202              <1> 	call	set_disk_parms
   260                              <1> 	; 10/12/2014
   261 00000072 81FE[DE66]          <1> 	cmp	si, fd0_type
   262 00000076 7705                <1> 	ja	short L4
   263 00000078 46                  <1> 	inc	si ; fd1_type
   264 00000079 B201                <1> 	mov	dl, 1
   265 0000007B EBE6                <1> 	jmp	short L3
   266                              <1> L4:
   267                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   268 0000007D B27F                <1> 	mov	dl, 7Fh
   269                              <1> 	; 24/12/2014 (Temporary)
   270 0000007F 803E[DD66]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   271 00000084 0F879000            <1>         ja      L10       ; yes, all fixed disk operations
   272                              <1> 			  ; will be performed according to
   273                              <1> 			  ; present EDD specification
   274                              <1> L6:
   275 00000088 FEC2                <1> 	inc 	dl
   276 0000008A 8816[DB66]          <1>         mov     [drv], dl
   277 0000008E 8816[DC66]          <1>         mov     [last_drv], dl ; 14/01/2015
   278 00000092 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   279 00000094 CD13                <1> 	int	13h	; (conventional function)
   280 00000096 0F828201            <1>         jc      L13	; fixed disk drive not ready
   281 0000009A 8816[DD66]          <1>         mov     [hdc], dl ; number of drives
   282                              <1> 	;; 14/01/2013
   283                              <1> 	;;push	cx
   284 0000009E E87302              <1> 	call	set_disk_parms
   285                              <1> 	;;pop	cx
   286                              <1> 	;
   287                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   288 000000A1 8A16[DB66]          <1>         mov     dl, [drv]
   289 000000A5 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   290 000000A8 80FA80              <1> 	cmp	dl, 80h
   291 000000AB 7603                <1> 	jna	short L7
   292 000000AD 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   293                              <1> L7:	
   294 000000B0 31C0                <1> 	xor	ax, ax
   295 000000B2 8ED8                <1> 	mov	ds, ax
   296 000000B4 8B37                <1>         mov     si, [bx]
   297 000000B6 8B4702              <1>         mov     ax, [bx+2] 
   298 000000B9 8ED8                <1> 	mov	ds, ax
   299 000000BB 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   300 000000BE 0F855601            <1>         jne     L12 ; invalid FDPT
   301 000000C2 BF0000              <1> 	mov	di, HD0_DPT
   302 000000C5 80FA80              <1> 	cmp	dl, 80h
   303 000000C8 7603                <1> 	jna	short L8
   304 000000CA BF2000              <1> 	mov	di, HD1_DPT 
   305                              <1> L8:
   306                              <1> 	; 30/12/2014
   307 000000CD B80090              <1> 	mov	ax, DPT_SEGM
   308 000000D0 8EC0                <1> 	mov	es, ax
   309                              <1> 	; 24/12/2014
   310 000000D2 B90800              <1> 	mov	cx, 8
   311 000000D5 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   312 000000D7 8CC8                <1> 	mov	ax, cs
   313 000000D9 8ED8                <1> 	mov	ds, ax
   314                              <1> 	; 02/02/2015
   315 000000DB 8A0E[DB66]          <1>         mov     cl, [drv]
   316 000000DF 88CB                <1> 	mov	bl, cl
   317 000000E1 B8F001              <1> 	mov	ax, 1F0h
   318 000000E4 80E301              <1> 	and	bl, 1
   319 000000E7 7406                <1> 	jz	short L9
   320 000000E9 C0E304              <1> 	shl	bl, 4
   321 000000EC 2D8000              <1> 	sub	ax, 1F0h-170h
   322                              <1> L9:
   323 000000EF AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   324 000000F0 050602              <1> 	add	ax, 206h
   325 000000F3 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   326 000000F4 88D8                <1> 	mov	al, bl
   327 000000F6 04A0                <1> 	add	al, 0A0h
   328 000000F8 AA                  <1> 	stosb	; Device/Head Register upper nibble
   329                              <1> 	;
   330 000000F9 FE06[DB66]          <1> 	inc	byte [drv]
   331 000000FD BB[6066]            <1> 	mov	bx, hd0_type - 80h
   332 00000100 01CB                <1> 	add	bx, cx
   333 00000102 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   334 00000105 A0[DD66]            <1> 	mov	al, [hdc]
   335 00000108 FEC8                <1> 	dec	al
   336 0000010A 0F840E01            <1>         jz      L13
   337 0000010E 80FA80              <1> 	cmp	dl, 80h
   338 00000111 0F8673FF            <1>         jna     L6
   339 00000115 E90401              <1>         jmp     L13
   340                              <1> L10:
   341 00000118 FEC2                <1> 	inc 	dl
   342                              <1> 	; 25/12/2014
   343 0000011A 8816[DB66]          <1> 	mov	[drv], dl
   344 0000011E B408                <1> 	mov 	ah, 08h ; Return drive parameters
   345 00000120 CD13                <1> 	int	13h	; (conventional function)
   346 00000122 0F82F600            <1>         jc      L13
   347                              <1> 	; 14/01/2015
   348 00000126 8A16[DB66]          <1> 	mov	dl, [drv]
   349 0000012A 52                  <1> 	push	dx
   350 0000012B 51                  <1> 	push	cx
   351 0000012C E8E501              <1> 	call	set_disk_parms
   352 0000012F 59                  <1> 	pop	cx
   353 00000130 5A                  <1> 	pop	dx
   354                              <1> 	; 04/02/2016 (esi -> si)
   355 00000131 BE[DC80]            <1> 	mov	si, _end ; 30 byte temporary buffer address 	
   356                              <1> 			 ; at the '_end' of kernel.
   357 00000134 C7041E00            <1> 	mov	word [si], 30
   358 00000138 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   359 0000013A CD13                <1> 	int	13h
   360 0000013C 0F82DC00            <1>         jc      L13
   361                              <1> 	; 04/02/2016 (ebx -> bx)
   362                              <1> 	; 14/01/2015
   363 00000140 29DB                <1> 	sub	bx, bx
   364 00000142 88D3                <1> 	mov	bl, dl
   365 00000144 80EB80              <1> 	sub	bl, 80h
   366 00000147 81C3[E066]          <1> 	add	bx, hd0_type
   367 0000014B 8A07                <1> 	mov 	al, [bx]
   368 0000014D 0C80                <1> 	or	al, 80h
   369 0000014F 8807                <1> 	mov 	[bx], al	
   370 00000151 81EB[DE66]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   371 00000155 81C3[2A67]          <1> 	add	bx, drv.status
   372 00000159 8807                <1> 	mov	[bx], al
   373                              <1> 	; 04/02/2016 (eax -> ax)
   374 0000015B 8B4410              <1> 	mov	ax, [si+16]
   375 0000015E 854412              <1> 	test	ax, [si+18]
   376 00000161 7412                <1> 	jz	short L10_A0h 
   377                              <1> 			; 'CHS only' disks on EDD system 
   378                              <1> 			;  are reported with ZERO disk size
   379 00000163 81EB[2A67]          <1> 	sub	bx, drv.status
   380 00000167 C1E302              <1> 	shl	bx, 2
   381 0000016A 81C3[0E67]          <1> 	add	bx, drv.size ; disk size (in sectors)
   382 0000016E 8907                <1> 	mov	[bx], ax
   383 00000170 8B4412              <1> 	mov	ax, [si+18]
   384 00000173 8907                <1> 	mov	[bx], ax
   385                              <1> 
   386                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   387                              <1> 	 ; for CHS disks (28/02/2015)
   388                              <1> 	; 30/12/2014
   389 00000175 BF0000              <1> 	mov	di, HD0_DPT
   390 00000178 88D0                <1> 	mov	al, dl
   391 0000017A 83E003              <1> 	and 	ax, 3
   392 0000017D C0E005              <1> 	shl	al, 5 ; *32
   393 00000180 01C7                <1> 	add 	di, ax
   394 00000182 B80090              <1> 	mov	ax, DPT_SEGM
   395 00000185 8EC0                <1> 	mov	es, ax
   396                              <1> 	;
   397 00000187 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   398 00000189 88CC                <1> 	mov	ah, cl	
   399 0000018B C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   400 0000018E 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   401 0000018F AB                  <1> 	stosw		
   402 00000190 88F0                <1> 	mov	al, dh	; max. head number
   403 00000192 FEC0                <1> 	inc	al
   404 00000194 AA                  <1> 	stosb		; logical heads (limits 256)
   405 00000195 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   406 00000197 AA                  <1> 	stosb
   407 00000198 8A440C              <1> 	mov	al, [si+12]
   408 0000019B AA                  <1> 	stosb		 ; physical sectors per track
   409 0000019C 31C0                <1>  	xor	ax, ax
   410                              <1> 	;dec	ax	 ; 02/01/2015 
   411 0000019E AB                  <1> 	stosw		 ; precompensation (obsolete)
   412                              <1> 	;xor	al, al	 ; 02/01/2015	
   413 0000019F AA                  <1> 	stosb		 ; reserved
   414 000001A0 B008                <1> 	mov	al, 8	 ; drive control byte
   415                              <1> 		         ; (do not disable retries, 
   416                              <1> 			 ; more than 8 heads)
   417 000001A2 AA                  <1> 	stosb
   418 000001A3 8B4404              <1> 	mov	ax, [si+4]
   419 000001A6 AB                  <1> 	stosw		 ; physical number of cylinders	
   420                              <1> 	;push	ax	 ; 02/01/2015
   421 000001A7 8A4408              <1> 	mov	al, [si+8]
   422 000001AA AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   423 000001AB 29C0                <1> 	sub 	ax, ax
   424                              <1> 	;pop	ax	 ; 02/01/2015	
   425 000001AD AB                  <1> 	stosw		 ; landing zone (obsolete)
   426 000001AE 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   427 000001B0 243F                <1> 	and 	al, 3Fh	
   428 000001B2 AA                  <1> 	stosb
   429                              <1> 	;sub	al, al	 ; checksum
   430                              <1> 	;stosb
   431                              <1> 	;
   432 000001B3 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   433 000001B6 AD                  <1> 	lodsw
   434 000001B7 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   435 000001B8 AD                  <1> 	lodsw
   436 000001B9 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   437                              <1> 	;
   438                              <1> 	; checksum calculation
   439 000001BA 89FE                <1> 	mov	si, di
   440 000001BC 06                  <1> 	push	es
   441 000001BD 1F                  <1> 	pop	ds
   442                              <1> 	;mov	cx, 16
   443 000001BE B90F00              <1> 	mov 	cx, 15
   444 000001C1 29CE                <1> 	sub	si, cx
   445 000001C3 30E4                <1> 	xor	ah, ah
   446                              <1> 	;del	cl
   447                              <1> L11:		
   448 000001C5 AC                  <1> 	lodsb
   449 000001C6 00C4                <1> 	add	ah, al
   450 000001C8 E2FB                <1> 	loop	L11
   451                              <1> 	;
   452 000001CA 88E0                <1> 	mov	al, ah
   453 000001CC F6D8                <1> 	neg	al	; -x+x = 0
   454 000001CE AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   455                              <1> 	;
   456 000001CF 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   457 000001D0 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   458                              <1> 	;
   459                              <1> 	; 23/02/2015
   460 000001D1 57                  <1> 	push	di
   461                              <1> 	; ES:DI points to DPTE (FDPTE) location
   462                              <1> 	;mov	cx, 8
   463 000001D2 B108                <1> 	mov	cl, 8
   464 000001D4 F3A5                <1> 	rep	movsw	
   465                              <1> 	;
   466                              <1> 	; 23/02/2015
   467                              <1> 	; (P)ATA drive and LBA validation
   468                              <1> 	; (invalidating SATA drives and setting
   469                              <1> 	; CHS type I/O for old type fixed disks)
   470 000001D6 5B                  <1> 	pop	bx
   471 000001D7 8CC8                <1> 	mov	ax, cs
   472 000001D9 8ED8                <1> 	mov	ds, ax
   473 000001DB 268B07              <1> 	mov	ax, [es:bx]
   474 000001DE 3DF001              <1> 	cmp	ax, 1F0h
   475 000001E1 7418                <1> 	je	short L11a
   476 000001E3 3D7001              <1> 	cmp	ax, 170h
   477 000001E6 7413                <1> 	je	short L11a
   478                              <1> 	; invalidation 
   479                              <1> 	; (because base port address is not 1F0h or 170h)
   480 000001E8 30FF                <1> 	xor	bh, bh
   481 000001EA 88D3                <1> 	mov	bl, dl
   482 000001EC 80EB80              <1> 	sub	bl, 80h
   483 000001EF C687[E066]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   484 000001F4 808F[2C67]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   485 000001F9 EB14                <1> 	jmp	short L11b
   486                              <1> L11a:	
   487                              <1> 	; LBA validation
   488 000001FB 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   489 000001FF A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   490 00000201 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   491                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   492 00000203 28FF                <1> 	sub	bh, bh
   493 00000205 88D3                <1> 	mov	bl, dl
   494 00000207 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   495 0000020A 80A7[2C67]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   496                              <1> 				; bit 0 = LBA ready bit
   497                              <1> 	; 'diskio' procedure will check this bit !
   498                              <1> L11b:
   499 0000020F 3A16[DC66]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   500 00000213 7307                <1>         jnb     short L13
   501 00000215 E900FF              <1>         jmp     L10
   502                              <1> L12:
   503                              <1> 	; Restore data registers
   504 00000218 8CC8                <1> 	mov	ax, cs
   505 0000021A 8ED8                <1> 	mov	ds, ax	
   506                              <1> L13:
   507                              <1> 	; 13/12/2014
   508 0000021C 0E                  <1> 	push	cs
   509 0000021D 07                  <1> 	pop	es
   510                              <1> L14:
   511 0000021E B411                <1> 	mov 	ah, 11h
   512 00000220 CD16                <1> 	int 	16h
   513 00000222 7406                <1> 	jz 	short L15 ; no keys in keyboard buffer
   514 00000224 B010                <1> 	mov	al, 10h
   515 00000226 CD16                <1> 	int 	16h
   516 00000228 EBF4                <1> 	jmp 	short L14
   517                              <1> L15:
   518                              <1> ; //////
   519                              <1> 	; 24/11/2014
   520                              <1> 	; 19/11/2014
   521                              <1> 	; 14/11/2014
   522                              <1> 	; Temporary code for disk searching code check
   523                              <1> 	;
   524                              <1> 	; This code will show existing (usable) drives and also
   525                              <1> 	; will show EDD interface support status for hard disks		
   526                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   527                              <1> 	; no need to get it again in protected mode...) 
   528                              <1> 	;	
   529                              <1> 	; 13/11/2014
   530 0000022A BB0700              <1> 	mov	bx, 7
   531 0000022D B40E                <1> 	mov	ah, 0Eh
   532 0000022F A0[DE66]            <1> 	mov	al, [fd0_type]
   533 00000232 20C0                <1> 	and	al, al
   534 00000234 743D                <1> 	jz	short L15a
   535 00000236 88C2                <1> 	mov	dl, al
   536 00000238 B046                <1> 	mov	al, 'F'
   537 0000023A CD10                <1> 	int 	10h
   538 0000023C B044                <1> 	mov	al, 'D'
   539 0000023E CD10                <1> 	int 	10h
   540 00000240 B030                <1> 	mov	al, '0'
   541 00000242 CD10                <1> 	int 	10h
   542 00000244 B020                <1> 	mov	al, ' '
   543 00000246 CD10                <1> 	int	10h
   544 00000248 E8B200              <1> 	call	L15c
   545 0000024B B020                <1> 	mov	al, ' '
   546 0000024D CD10                <1> 	int	10h
   547                              <1> 	;
   548 0000024F A0[DF66]            <1> 	mov	al, [fd1_type]
   549 00000252 20C0                <1> 	and	al, al
   550 00000254 741D                <1> 	jz	short L15a
   551 00000256 88C2                <1> 	mov	dl, al
   552 00000258 B046                <1> 	mov	al, 'F'
   553 0000025A CD10                <1> 	int 	10h
   554 0000025C B044                <1> 	mov	al, 'D'
   555 0000025E CD10                <1> 	int 	10h
   556 00000260 B031                <1> 	mov	al, '1'
   557 00000262 CD10                <1> 	int 	10h
   558 00000264 B020                <1> 	mov	al, ' '
   559 00000266 CD10                <1> 	int	10h
   560 00000268 E89200              <1> 	call	L15c
   561 0000026B B020                <1> 	mov	al, ' '
   562 0000026D CD10                <1> 	int	10h
   563 0000026F B020                <1> 	mov	al, ' '
   564 00000271 CD10                <1> 	int	10h
   565                              <1> L15a:
   566 00000273 A0[E066]            <1> 	mov	al, [hd0_type]
   567 00000276 20C0                <1> 	and	al, al
   568 00000278 7479                <1> 	jz	short L15b
   569 0000027A 88C2                <1> 	mov	dl, al
   570 0000027C B048                <1> 	mov	al, 'H'
   571 0000027E CD10                <1> 	int 	10h
   572 00000280 B044                <1> 	mov	al, 'D'
   573 00000282 CD10                <1> 	int 	10h
   574 00000284 B030                <1> 	mov	al, '0'
   575 00000286 CD10                <1> 	int 	10h
   576 00000288 B020                <1> 	mov	al, ' '
   577 0000028A CD10                <1> 	int 	10h
   578 0000028C E86E00              <1> 	call	L15c
   579 0000028F B020                <1> 	mov	al, ' '
   580 00000291 CD10                <1> 	int	10h
   581                              <1> 	;
   582 00000293 A0[E166]            <1> 	mov	al, [hd1_type]
   583 00000296 20C0                <1> 	and	al, al
   584 00000298 7459                <1> 	jz	short L15b
   585 0000029A 88C2                <1> 	mov	dl, al
   586 0000029C B048                <1> 	mov	al, 'H'
   587 0000029E CD10                <1> 	int 	10h
   588 000002A0 B044                <1> 	mov	al, 'D'
   589 000002A2 CD10                <1> 	int 	10h
   590 000002A4 B031                <1> 	mov	al, '1'
   591 000002A6 CD10                <1> 	int 	10h
   592 000002A8 B020                <1> 	mov	al, ' '
   593 000002AA CD10                <1> 	int 	10h
   594 000002AC E84E00              <1> 	call	L15c
   595 000002AF B020                <1> 	mov	al, ' '
   596 000002B1 CD10                <1> 	int	10h
   597                              <1> 	;
   598 000002B3 A0[E266]            <1> 	mov	al, [hd2_type]
   599 000002B6 20C0                <1> 	and	al, al
   600 000002B8 7439                <1> 	jz	short L15b
   601 000002BA 88C2                <1> 	mov	dl, al
   602 000002BC B048                <1> 	mov	al, 'H'
   603 000002BE CD10                <1> 	int 	10h
   604 000002C0 B044                <1> 	mov	al, 'D'
   605 000002C2 CD10                <1> 	int 	10h
   606 000002C4 B032                <1> 	mov	al, '2'
   607 000002C6 CD10                <1> 	int 	10h
   608 000002C8 B020                <1> 	mov	al, ' '
   609 000002CA CD10                <1> 	int 	10h
   610 000002CC E82E00              <1> 	call	L15c
   611 000002CF B020                <1> 	mov	al, ' '
   612 000002D1 CD10                <1> 	int	10h
   613                              <1> 	;
   614 000002D3 A0[E366]            <1> 	mov	al, [hd3_type]
   615 000002D6 20C0                <1> 	and	al, al
   616 000002D8 7419                <1> 	jz	short L15b
   617 000002DA 88C2                <1> 	mov	dl, al
   618 000002DC B048                <1> 	mov	al, 'H'
   619 000002DE CD10                <1> 	int 	10h
   620 000002E0 B044                <1> 	mov	al, 'D'
   621 000002E2 CD10                <1> 	int 	10h
   622 000002E4 B033                <1> 	mov	al, '3'
   623 000002E6 CD10                <1> 	int 	10h
   624 000002E8 B020                <1> 	mov	al, ' '
   625 000002EA CD10                <1> 	int 	10h
   626 000002EC E80E00              <1> 	call	L15c
   627 000002EF B020                <1> 	mov	al, ' '
   628 000002F1 CD10                <1> 	int	10h
   629                              <1> 	;
   630                              <1> L15b:
   631 000002F3 B00D                <1> 	mov	al, 0Dh
   632 000002F5 CD10                <1> 	int 	10h	
   633 000002F7 B00A                <1> 	mov	al, 0Ah
   634 000002F9 CD10                <1> 	int 	10h
   635                              <1> 	;;xor	ah, ah
   636                              <1> 	;;int 	16h	
   637                              <1> 	;
   638 000002FB EB77                <1>         jmp     L16  ; jmp short L16
   639                              <1>         ;
   640                              <1> L15c:
   641 000002FD 88D6                <1> 	mov	dh, dl
   642 000002FF C0EE04              <1> 	shr	dh, 4
   643 00000302 80C630              <1> 	add	dh, 30h
   644 00000305 80E20F              <1> 	and	dl, 15
   645 00000308 80C230              <1> 	add	dl, 30h
   646 0000030B 88F0                <1> 	mov	al, dh
   647 0000030D CD10                <1> 	int	10h
   648 0000030F 88D0                <1> 	mov	al, dl
   649 00000311 CD10                <1> 	int	10h
   650 00000313 C3                  <1> 	retn
   651                              <1> 	;
   652                              <1> 	; end of temporary code for disk searching code check
   653                              <1> 
   654                              <1> ; //////
   655                              <1> 
   656                              <1> set_disk_parms:
   657                              <1> 	; 04/02/2016 (ebx -> bx)
   658                              <1> 	; 10/07/2015
   659                              <1> 	; 14/01/2015
   660                              <1> 	;push	bx
   661 00000314 28FF                <1> 	sub	bh, bh
   662 00000316 8A1E[DB66]          <1> 	mov	bl, [drv]
   663 0000031A 80FB80              <1> 	cmp	bl, 80h
   664 0000031D 7203                <1> 	jb	short sdp0
   665 0000031F 80EB7E              <1> 	sub	bl, 7Eh
   666                              <1> sdp0:	
   667 00000322 81C3[2A67]          <1> 	add	bx, drv.status
   668 00000326 C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   669                              <1> 	;
   670 00000329 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   671 0000032B 88CC                <1> 	mov	ah, cl ; 
   672 0000032D C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   673 00000330 81EB[2A67]          <1> 	sub	bx, drv.status
   674 00000334 D0E3                <1> 	shl	bl, 1
   675 00000336 81C3[E466]          <1> 	add	bx, drv.cylinders
   676 0000033A 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   677 0000033B 8907                <1> 	mov	[bx], ax
   678 0000033D 50                  <1> 	push	ax ; ** cylinders
   679 0000033E 81EB[E466]          <1> 	sub	bx, drv.cylinders
   680 00000342 81C3[F266]          <1> 	add	bx, drv.heads
   681 00000346 30E4                <1> 	xor	ah, ah
   682 00000348 88F0                <1> 	mov	al, dh ; heads
   683 0000034A 40                  <1> 	inc	ax
   684 0000034B 8907                <1> 	mov	[bx], ax
   685 0000034D 81EB[F266]          <1>         sub     bx, drv.heads
   686 00000351 81C3[0067]          <1>         add     bx, drv.spt
   687 00000355 30ED                <1> 	xor	ch, ch
   688 00000357 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   689 0000035A 890F                <1> 	mov	[bx], cx
   690 0000035C 81EB[0067]          <1>         sub     bx, drv.spt
   691 00000360 D1E3                <1> 	shl	bx, 1
   692 00000362 81C3[0E67]          <1> 	add	bx, drv.size ; disk size (in sectors)
   693                              <1> 	; LBA size = cylinders * heads * secpertrack
   694 00000366 F7E1                <1> 	mul	cx 
   695 00000368 89C2                <1> 	mov	dx, ax	; heads*spt					
   696 0000036A 58                  <1> 	pop	ax ; ** cylinders
   697 0000036B 48                  <1> 	dec	ax ; 1 cylinder reserved (!?)
   698 0000036C F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   699 0000036E 8907                <1> 	mov	[bx], ax
   700 00000370 895702              <1> 	mov	[bx+2], dx
   701                              <1> 	;
   702                              <1> 	;pop	bx
   703 00000373 C3                  <1> 	retn
   704                              <1> 
   705                              <1> ;align 2
   706                              <1> 
   707                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   708                              <1> ;heads	  :  dw 0, 0, 0, 0, 0, 0
   709                              <1> ;spt	  :  dw 0, 0, 0, 0, 0, 0
   710                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   711                              <1> 
   712                              <1> ;last_drv:
   713                              <1> ;	db  0
   714                              <1> ;drv_status:
   715                              <1> ;	db  0,0,0,0,0,0
   716                              <1> ;	db 0
   717                              <1> 
   718                              <1> 
   719                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   720                              <1> 
   721                              <1> L16:
   202                                  
   203                                  	; 10/11/2014
   204 00000374 FA                           	cli	; Disable interrupts (clear interrupt flag)
   205                                  		; Reset Interrupt MASK Registers (Master&Slave)
   206                                  	;mov	al, 0FFh	; mask off all interrupts
   207                                  	;out	21h, al		; on master PIC (8259)
   208                                  	;jmp 	$+2  ; (delay)
   209                                  	;out	0A1h, al	; on slave PIC (8259)
   210                                  	;
   211                                  	; Disable NMI 
   212 00000375 B080                    	mov   	al, 80h 
   213 00000377 E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   214                                  	;23/02/2015
   215 00000379 90                      	nop			;
   216                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   217                                  				; for preventing unknown state (!?)
   218                                  	;
   219                                   	; 20/08/2014
   220                                  	; Moving the kernel 64 KB back (to physical address 0)
   221                                  	; DS = CS = 1000h
   222                                  	; 05/11/2014
   223 0000037A 31C0                    	xor	ax, ax
   224 0000037C 8EC0                    	mov	es, ax ; ES = 0
   225                                  	;
   226 0000037E B90040                  	mov	cx, (KEND - KLOAD)/4
   227 00000381 31F6                    	xor	si, si
   228 00000383 31FF                    	xor	di, di
   229 00000385 F366A5                  	rep	movsd
   230                                  	;
   231 00000388 06                      	push	es ; 0
   232 00000389 68[8D03]                	push	L17
   233 0000038C CB                      	retf
   234                                  	;
   235                                  L17:
   236                                  	; Turn off the floppy drive motor
   237 0000038D BAF203                          mov     dx, 3F2h
   238 00000390 EE                              out     dx, al ; 0 ; 31/12/2013
   239                                  
   240                                  	; Enable access to memory above one megabyte
   241                                  L18:
   242 00000391 E464                    	in	al, 64h
   243 00000393 A802                    	test	al, 2
   244 00000395 75FA                            jnz     short L18
   245 00000397 B0D1                    	mov	al, 0D1h	; Write output port
   246 00000399 E664                    	out	64h, al
   247                                  L19:
   248 0000039B E464                    	in	al, 64h
   249 0000039D A802                    	test	al, 2
   250 0000039F 75FA                            jnz     short L19
   251 000003A1 B0DF                    	mov	al, 0DFh	; Enable A20 line
   252 000003A3 E660                    	out	60h, al
   253                                  ;L20:
   254                                  	;
   255                                  	; Load global descriptor table register
   256                                  
   257                                          ;mov     ax, cs
   258                                          ;mov     ds, ax
   259                                  
   260 000003A5 2E0F0116[0064]                  lgdt    [cs:gdtd]
   261                                  
   262 000003AB 0F20C0                          mov     eax, cr0
   263                                  	; or 	eax, 1
   264 000003AE 40                      	inc     ax
   265 000003AF 0F22C0                  	mov     cr0, eax
   266                                  
   267                                  	; Jump to 32 bit code
   268                                  	
   269 000003B2 66                      	db 66h 			; Prefix for 32-bit
   270 000003B3 EA                      	db 0EAh 		; Opcode for far jump
   271 000003B4 [BA030000]              	dd StartPM 		; Offset to start, 32-bit
   272                                  				; (1000h:StartPM = StartPM + 10000h)
   273 000003B8 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   274                                  				; assuming that StartPM resides in code32
   275                                  
   276                                  [BITS 32] 
   277                                  
   278                                  StartPM:
   279                                  	; Kernel Base Address = 0 ; 30/12/2013
   280 000003BA 66B81000                	mov ax, KDATA           ; Save data segment identifier
   281 000003BE 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   282 000003C0 8EC0                           	mov es, ax              ; Move data segment into ES register
   283 000003C2 8EE0                           	mov fs, ax              ; Move data segment into FS register
   284 000003C4 8EE8                          	mov gs, ax              ; Move data segment into GS register
   285 000003C6 8ED0                            mov ss, ax              ; Move data segment into SS register
   286 000003C8 BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   287                                  
   288                                  clear_bss: ; Clear uninitialized data area
   289                                  	; 11/03/2015
   290 000003CD 31C0                    	xor  eax, eax ; 0
   291 000003CF B9C7050000              	mov  ecx, (bss_end - bss_start)/4
   292                                  	;shr  ecx, 2 ; bss section is already aligned for double words
   293 000003D4 BF[C0690000]            	mov  edi, bss_start	
   294 000003D9 F3AB                    	rep  stosd  		
   295                                  
   296                                  memory_init:
   297                                  	; Initialize memory allocation table and page tables
   298                                  	; 16/11/2014
   299                                  	; 15/11/2014
   300                                  	; 07/11/2014
   301                                  	; 06/11/2014
   302                                  	; 05/11/2014
   303                                  	; 04/11/2014
   304                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   305                                  	;
   306                                  ;	xor	eax, eax
   307                                  ;	xor 	ecx, ecx
   308 000003DB B108                    	mov	cl, 8
   309 000003DD BF00001000              	mov	edi, MEM_ALLOC_TBL	
   310 000003E2 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   311                                  				   ; for the first 1 MB memory
   312                                  	;
   313 000003E4 668B0D[B0690000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   314                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   315 000003EB 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   316 000003EF 890D[306C0000]          	mov	[free_pages], ecx
   317 000003F5 668B15[B2690000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   318                                  				   ; between 16 MB and 4 GB.	
   319 000003FC 6609D2                  	or	dx, dx
   320 000003FF 7413                    	jz	short mi_0
   321                                  	;
   322 00000401 6689D0                  	mov	ax, dx
   323 00000404 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   324 00000407 0105[306C0000]          	add	[free_pages], eax
   325 0000040D 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   326 00000412 EB07                    	jmp	short mi_1
   327                                  mi_0:
   328 00000414 6689C8                  	mov	ax, cx
   329 00000417 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   330                                  mi_1:
   331 0000041B A3[2C6C0000]            	mov	[memory_size], eax ; Total available memory in pages
   332                                  				   ; 1 alloc. tbl. bit = 1 memory page
   333                                  				   ; 32 allocation bits = 32 mem. pages   
   334                                  	;
   335 00000420 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   336 00000425 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   337                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   338                                  				   ;  --> x M.A.T. pages, if y = 0
   339 00000428 66A3[406C0000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   340 0000042E C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   341                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   342 00000431 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   343                                  	; Set/Calculate Kernel's Page Directory Address
   344 00000433 81C300001000            	add	ebx, MEM_ALLOC_TBL
   345 00000439 891D[286C0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   346                                  				   ; just after the last M.A.T. page
   347                                  	;
   348 0000043F 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   349 00000442 A3[386C0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   350                                  	;			   ; (allocation status search must be 
   351                                  				   ; stopped after here)	
   352 00000447 31C0                    	xor	eax, eax
   353 00000449 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   354 0000044A 6651                    	push	cx
   355 0000044C C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   356                                  				   ; count of 32 allocation bits
   357 0000044F F3AB                    	rep	stosd
   358 00000451 6659                    	pop	cx
   359 00000453 40                      	inc	eax		   ; 0	
   360 00000454 80E11F                  	and	cl, 31		   ; remain bits
   361 00000457 7412                    	jz	short mi_4
   362 00000459 8907                    	mov	[edi], eax	   ; reset	
   363                                  mi_2:
   364 0000045B 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   365 0000045E FEC9                    	dec	cl
   366 00000460 7404                    	jz	short mi_3
   367 00000462 FEC0                    	inc	al
   368 00000464 EBF5                    	jmp	short mi_2
   369                                  mi_3:
   370 00000466 28C0                    	sub	al, al	   	   ; 0
   371 00000468 83C704                  	add	edi, 4		   ; 15/11/2014
   372                                  mi_4:
   373 0000046B 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   374 0000046E 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   375                                  	;	
   376 00000470 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   377                                  	;	
   378 00000475 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   379 00000477 7406                    	jz	short mi_5	  ; jump if EDI points to 
   380                                  				  ;         end of first 16 MB	
   381 00000479 D1E9                    	shr	ecx, 1		  ; convert to dword count
   382 0000047B D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   383 0000047D F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   384                                  				  ; (memory hole under 16 MB)
   385                                  mi_5:
   386 0000047F 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   387 00000482 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   388 00000484 9C                      	pushf			  ; 16/11/2014		
   389 00000485 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   390 00000486 F3AB                    	rep	stosd
   391 00000488 40                      	inc	eax		  ; 0
   392 00000489 9D                      	popf			  ; 16/11/2014
   393 0000048A 7305                    	jnc	short mi_6
   394 0000048C 6648                    	dec	ax		  ; eax = 0000FFFFh
   395 0000048E AB                      	stosd
   396 0000048F 6640                    	inc	ax		  ; 0		
   397                                  mi_6:
   398 00000491 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   399 00000493 730A                    	jnb	short mi_7	  ; end of memory allocation table
   400                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   401 00000495 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   402 00000497 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   403 00000499 D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   404 0000049B D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   405 0000049D F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   406                                  mi_7:
   407                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   408 0000049F BA00001000              	mov	edx, MEM_ALLOC_TBL
   409                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   410                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   411 000004A4 668B0D[406C0000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   412 000004AB 89D7                    	mov	edi, edx
   413 000004AD C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   414                                  				  ; byte offset in M.A.T.
   415                                  				  ; (1 M.A.T. byte points to 
   416                                  				  ;	      32768 bytes)
   417                                  				  ; Note: MEM_ALLOC_TBL address 
   418                                  				  ; must be aligned on 128 KB 
   419                                  				  ; boundary!
   420 000004B0 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   421                                  	; eax = 0
   422 000004B2 290D[306C0000]          	sub	[free_pages], ecx ; 07/11/2014
   423                                  mi_8:
   424 000004B8 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   425                                  	;dec	bl
   426 000004BB FEC9                    	dec	cl
   427 000004BD 7404                    	jz	short mi_9
   428 000004BF FEC0                    	inc	al
   429 000004C1 EBF5                    	jmp	short mi_8
   430                                  mi_9:
   431                                  	;
   432                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   433                                  	;		(allocate pages for system page tables)
   434                                  
   435                                  	; edx = MEM_ALLOC_TBL
   436 000004C3 8B0D[2C6C0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   437 000004C9 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   438 000004CF C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   439                                  				 ; page table count (PDE count)
   440                                  	;
   441 000004D2 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   442                                  	;
   443 000004D3 41                      	inc	ecx		 ; +1 for kernel page directory	
   444                                  	;
   445 000004D4 290D[306C0000]          	sub	[free_pages], ecx ; 07/11/2014
   446                                  	;
   447 000004DA 8B35[286C0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   448 000004E0 C1EE0C                  	shr	esi, 12		 ; convert to page number
   449                                  mi_10:
   450 000004E3 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   451 000004E5 89C3                    	mov	ebx, eax
   452 000004E7 C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   453 000004EA 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   454                                  				 ;   to align on dword boundary
   455 000004ED 83E01F                  	and	eax, 31		 ; set allocation bit position 
   456                                  				 ;  (bit 0 to bit 31)
   457                                  	;
   458 000004F0 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   459                                  	;
   460 000004F2 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   461                                  	;
   462 000004F5 46                      	inc	esi		 ; next page table
   463 000004F6 E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   464                                  				 ; (ecx = page table count + 1)		
   465                                  	;
   466 000004F8 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   467                                  	;
   468                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   469                                  	;
   470                                  	; Initialize Kernel's Page Directory
   471 000004F9 8B3D[286C0000]          	mov	edi, [k_page_dir]
   472 000004FF 89F8                    	mov	eax, edi
   473 00000501 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   474                                  		     	      ; supervisor + read&write + present
   475 00000503 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   476                                  mi_11:
   477 00000505 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   478                                  			        ; EAX points to next page table
   479 0000050A AB                      	stosd
   480 0000050B E2F8                    	loop	mi_11
   481 0000050D 29C0                    	sub	eax, eax	; Empty PDE
   482 0000050F 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   483 00000513 29D1                    	sub	ecx, edx
   484 00000515 7402                    	jz	short mi_12
   485 00000517 F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   486                                  	;
   487                                  	; Initialization of Kernel's Page Directory is OK, here.
   488                                  mi_12:
   489                                  	; Initialize Kernel's Page Tables
   490                                  	;
   491                                  	; (EDI points to address of page table 0)
   492                                  	; eax = 0
   493 00000519 8B0D[2C6C0000]          	mov	ecx, [memory_size] ; memory size in pages
   494 0000051F 89CA                    	mov	edx, ecx	; (***)
   495 00000521 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   496                                  			     ; supervisor + read&write + present 	
   497                                  mi_13:
   498 00000523 AB                      	stosd
   499 00000524 0500100000              	add	eax, 4096	
   500 00000529 E2F8                    	loop	mi_13	
   501 0000052B 6681E2FF03              	and	dx, 1023	; (***)
   502 00000530 740B                    	jz	short mi_14
   503 00000532 66B90004                	mov	cx, 1024	
   504 00000536 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   505 00000539 31C0                    	xor	eax, eax
   506 0000053B F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   507                                  				; of the last page table
   508                                  mi_14:
   509                                  	;  Initialization of Kernel's Page Tables is OK, here.
   510                                  	;
   511 0000053D 89F8                    	mov	eax, edi	; end of the last page table page
   512                                  			        ; (beginging of user space pages)
   513 0000053F C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   514 00000542 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   515                                  				; aligning on dword boundary	
   516                                  	 
   517 00000544 A3[3C6C0000]            	mov	[first_page], eax
   518 00000549 A3[346C0000]            	mov	[next_page], eax ; The first free page pointer
   519                                  				 ; for user programs
   520                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   521                                  	;
   522                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   523                                  	;
   524                                  	
   525                                  	; Enable paging
   526                                  	;
   527 0000054E A1[286C0000]                    mov     eax, [k_page_dir]
   528 00000553 0F22D8                  	mov	cr3, eax
   529 00000556 0F20C0                  	mov	eax, cr0
   530 00000559 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   531 0000055E 0F22C0                  	mov	cr0, eax
   532                                          ;jmp    KCODE:StartPMP
   533                                  
   534 00000561 EA                      	db 0EAh 		; Opcode for far jump
   535 00000562 [68050000]                      dd StartPMP		; 32 bit offset
   536 00000566 0800                    	dw KCODE		; kernel code segment descriptor
   537                                  
   538                                  
   539                                  StartPMP:
   540                                  	; 06/11//2014
   541                                  	; Clear video page 0
   542                                  	;
   543                                  	; Temporary Code
   544                                  	;
   545 00000568 B9E8030000              	mov	ecx, 80*25/2
   546 0000056D BF00800B00              	mov	edi, 0B8000h
   547 00000572 31C0                    	xor	eax, eax	; black background, black fore color
   548 00000574 F3AB                    	rep	stosd
   549                                  	
   550                                  	; 19/08/2014
   551                                  	; Kernel Base Address = 0
   552                                  	; It is mapped to (physically) 0 in the page table.
   553                                  	; So, here is exactly 'StartPMP' address.
   554                                  	;
   555                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   556                                  	;;mov	esi, msgPM
   557                                  	;; 14/08/2015 (kernel version message will appear
   558                                  	;;	       when protected mode and paging is enabled)
   559 00000576 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   560 00000578 BE[40670000]            	mov	esi, msgKVER
   561 0000057D BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   562                                  	; 20/08/2014
   563 00000582 E893010000              	call	printk
   564                                  
   565                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   566                                  	; // Set IRQ offsets
   567                                  	;
   568                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   569                                  	;
   570                                  					;; ICW1
   571 00000587 B011                    	mov	al, 11h			; Initialization sequence
   572 00000589 E620                    	out	20h, al			; 	8259A-1
   573                                  	; jmp 	$+2
   574 0000058B E6A0                    	out	0A0h, al		; 	8259A-2
   575                                  					;; ICW2
   576 0000058D B020                    	mov	al, 20h			; Start of hardware ints (20h)
   577 0000058F E621                    	out	21h, al			;	for 8259A-1
   578                                  	; jmp 	$+2
   579 00000591 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   580 00000593 E6A1                    	out	0A1h, al		; 	for 8259A-2
   581                                  					;
   582 00000595 B004                    	mov	al, 04h			;; ICW3
   583 00000597 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   584                                  	; jmp 	$+2
   585 00000599 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   586 0000059B E6A1                    	out	0A1h, al		;
   587                                  					;; ICW4
   588 0000059D B001                    	mov	al, 01h	 		;
   589 0000059F E621                    	out	21h, al			; 	8086 mode, normal EOI	
   590                                  	; jmp 	$+2
   591 000005A1 E6A1                    	out	0A1h, al		;	for both chips.
   592                                  
   593                                  	;mov	al, 0FFh	; mask off all interrupts for now
   594                                  	;out	21h, al
   595                                  	;; jmp 	$+2
   596                                  	;out	0A1h, al
   597                                  
   598                                  	; 02/04/2015
   599                                  	; 26/03/2015 System call (INT 30h) modification
   600                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   601                                  	;
   602                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   603                                  	;  setup_idt:
   604                                  	;
   605                                          ;; 16/02/2015
   606                                  	;;mov     dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   607                                  	; 21/08/2014 (timer_int)
   608 000005A3 BE[0C640000]            	mov	esi, ilist
   609 000005A8 8D3D[C0690000]          	lea	edi, [idt]
   610                                  	; 26/03/2015
   611 000005AE B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   612                                  	; 02/04/2015
   613 000005B3 BB00000800              	mov	ebx,  80000h
   614                                  rp_sidt1:
   615 000005B8 AD                      	lodsd
   616 000005B9 89C2                    	mov	edx, eax
   617 000005BB 66BA008E                	mov	dx, 8E00h
   618 000005BF 6689C3                  	mov	bx, ax
   619 000005C2 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   620                                         			        ; /* interrupt gate - dpl=0, present */
   621 000005C4 AB                      	stosd	; selector & offset bits 0-15 	
   622 000005C5 89D0                    	mov	eax, edx
   623 000005C7 AB                      	stosd	; attributes & offset bits 16-23
   624 000005C8 E2EE                    	loop	rp_sidt1
   625 000005CA B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   626                                  rp_sidt2:
   627 000005CC AD                      	lodsd
   628 000005CD 21C0                    	and	eax, eax
   629 000005CF 7413                    	jz	short rp_sidt3
   630 000005D1 89C2                    	mov	edx, eax
   631 000005D3 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   632 000005D7 6689C3                  	mov	bx, ax
   633 000005DA 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   634 000005DC AB                      	stosd
   635 000005DD 89D0                    	mov	eax, edx
   636 000005DF AB                      	stosd
   637 000005E0 E2EA                    	loop	rp_sidt2
   638 000005E2 EB16                    	jmp	short sidt_OK
   639                                  rp_sidt3:
   640 000005E4 B8[3F0A0000]            	mov	eax, ignore_int
   641 000005E9 89C2                    	mov	edx, eax
   642 000005EB 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   643 000005EF 6689C3                  	mov	bx, ax
   644 000005F2 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   645                                  rp_sidt4:
   646 000005F4 AB                      	stosd
   647 000005F5 92                      	xchg	eax, edx
   648 000005F6 AB                      	stosd
   649 000005F7 92                      	xchg	edx, eax
   650 000005F8 E2FA                    	loop	rp_sidt4
   651                                  sidt_OK: 
   652 000005FA 0F011D[06640000]        	lidt 	[idtd]
   653                                  	;
   654                                  	; TSS descriptor setup ; 24/03/2015
   655 00000601 B8[C06B0000]            	mov	eax, task_state_segment
   656 00000606 66A3[FA630000]          	mov	[gdt_tss0], ax
   657 0000060C C1C010                  	rol	eax, 16
   658 0000060F A2[FC630000]            	mov	[gdt_tss1], al
   659 00000614 8825[FF630000]          	mov	[gdt_tss2], ah
   660 0000061A 66C705[266C0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   660 00000622 00                 
   661                                  		; 
   662                                  		; IO Map Base address (When this address points
   663                                  		; to end of the TSS, CPU does not use IO port 
   664                                  		; permission bit map for RING 3 IO permissions, 
   665                                  		; access to any IO ports in ring 3 will be forbidden.)
   666                                   		;
   667                                  	;mov	[tss.esp0], esp ; TSS offset 4
   668                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   669 00000623 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   670                                  			 ; occurs (or a system call -software INT- is requested)
   671                                  			 ; while cpu running in ring 3 (in user mode).				
   672                                  			 ; (Kernel stack pointer and segment will be loaded
   673                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   674 00000627 0F00D8                  	ltr	ax  ; Load task register
   675                                  	;
   676                                  esp0_set0:
   677                                  	; 30/07/2015
   678 0000062A 8B0D[2C6C0000]          	mov 	ecx, [memory_size] ; memory size in pages
   679 00000630 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   680 00000633 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   681                                  			  ; (kernel mode virtual address)
   682 00000639 7605                    	jna	short esp0_set1
   683                                  	;
   684                                  	; If available memory > CORE (end of the 1st 4 MB)
   685                                  	; set stack pointer to CORE
   686                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   687                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   688 0000063B B900004000              	mov	ecx, CORE
   689                                  esp0_set1:
   690 00000640 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   691                                  esp0_set_ok:
   692                                  	; 30/07/2015 (**tss.esp0**) 
   693 00000642 8925[C46B0000]          	mov	[tss.esp0], esp
   694 00000648 66C705[C86B0000]10-             mov     word [tss.ss0], KDATA
   694 00000650 00                 
   695                                  	; 14/08/2015
   696                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   697                                  	;
   698                                  	;cli	; Disable interrupts (for CPU)
   699                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   700                                  	;
   701 00000651 30C0                    	xor	al, al		; Enable all hardware interrupts!
   702 00000653 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   703 00000655 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   704 00000657 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   705                                  				; (Even if related hardware component
   706                                  				;  does not exist!)
   707                                  	; Enable NMI 
   708 00000659 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   709 0000065B E670                    	out  	70h, al
   710                                  	; 23/02/2015
   711 0000065D 90                      	nop
   712 0000065E E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   713                                  				; for preventing unknown state (!?)
   714                                  	;
   715                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   716                                  	;
   717                                  	; 02/09/2014
   718 00000660 6631DB                  	xor	bx, bx
   719 00000663 66BA0002                	mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   720 00000667 E83E0F0000              	call	set_cpos
   721                                  	;
   722                                  	; 06/11/2014
   723                                  	; Temporary Code
   724                                  	;
   725 0000066C E85B110000              	call	memory_info
   726                                  	; 14/08/2015
   727                                  	;call getch ; 28/02/2015
   728                                  drv_init:
   729 00000671 FB                      	sti	; Enable Interrupts 
   730                                  	; 06/02/2015
   731 00000672 8B15[E0660000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   732 00000678 668B1D[DE660000]        	mov	bx, [fd0_type] ; fd0, fd1
   733                                  	; 22/02/2015
   734 0000067F 6621DB                  	and	bx, bx
   735 00000682 751B                    	jnz	short di1
   736                                  	;
   737 00000684 09D2                    	or 	edx, edx
   738 00000686 7529                    	jnz	short di2
   739                                  	;
   740                                  setup_error:
   741 00000688 BE[65680000]            	mov 	esi, setup_error_msg
   742                                  psem:	
   743 0000068D AC                      	lodsb
   744 0000068E 08C0                    	or	al, al
   745                                  	;jz	short haltx ; 22/02/2015
   746 00000690 7426                    	jz	short di3
   747 00000692 56                      	push	esi
   748 00000693 31DB                    	xor	ebx, ebx ; 0
   749                                  			; Video page 0 (bl=0)
   750 00000695 B407                    	mov	ah, 07h ; Black background, 
   751                                  			; light gray forecolor
   752 00000697 E8EC0D0000              	call	write_tty
   753 0000069C 5E                      	pop	esi
   754 0000069D EBEE                    	jmp	short psem
   755                                  
   756                                  di1:
   757                                  	; supress 'jmp short T6'
   758                                  	;  (activate fdc motor control code)
   759 0000069F 66C705[9B070000]90-     	mov	word [T5], 9090h ; nop
   759 000006A7 90                 
   760                                  	;
   761                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   762                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   763                                  	;stosw
   764                                  	;mov 	ax, cs
   765                                  	;stosw
   766                                  	;; 16/02/2015
   767                                          ;;mov     dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   768                                  	;
   769 000006A8 E835200000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   770                                  	;
   771 000006AD 09D2                    	or	edx, edx
   772 000006AF 7407                            jz      short di3
   773                                  di2:
   774 000006B1 E872200000              	call   	DISK_SETUP	; Initialize Fixed Disks
   775 000006B6 72D0                            jc      short setup_error
   776                                  di3:
   777 000006B8 E8E3100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   778                                  	;
   779 000006BD E8675C0000              	call	display_disks ; 07/03/2015  (Temporary)
   780                                  ;haltx:
   781                                  	; 14/08/2015
   782                                  	;call	getch ; 22/02/2015
   783 000006C2 FB                      	sti	; Enable interrupts (for CPU)
   784                                  	; 14/08/2015
   785                                  	;mov 	ecx, 0FFFFFFFh
   786                                  	; 24/12/2021
   787 000006C3 B9FFFF2F00              	mov 	ecx, 02FFFFFh
   788                                  md_info_msg_wait:
   789 000006C8 51                      	push 	ecx
   790 000006C9 B001                    	mov	al, 1
   791 000006CB 8A25[566C0000]          	mov 	ah, [ptty] ; active (current) video page
   792 000006D1 E89E590000              	call	getc_n
   793 000006D6 59                      	pop	ecx
   794 000006D7 7502                    	jnz	short md_info_msg_ok
   795 000006D9 E2ED                    	loop	md_info_msg_wait
   796                                  md_info_msg_ok:
   797                                  	; 30/06/2015
   798 000006DB E8532D0000              	call	sys_init
   799                                  	;
   800                                  	;jmp 	cpu_reset ; 22/02/2015
   801                                  hang:
   802                                  	; 24/12/2021
   803 000006E0 29C0                    	sub	eax, eax
   804                                  _hang:	
   805                                  	; 23/02/2015
   806                                  	;sti			; Enable interrupts
   807 000006E2 F4                      	hlt
   808                                  	;
   809                                  	;nop
   810                                  	;; 03/12/2014
   811                                  	;; 28/08/2014
   812                                  	;mov	ah, 11h
   813                                  	;call	getc
   814                                  	;jz      _c8
   815                                  	;
   816                                  	; 23/02/2015
   817                                  	; 06/02/2015
   818                                  	; 07/09/2014
   819 000006E3 31DB                    	xor	ebx, ebx
   820 000006E5 8A1D[566C0000]          	mov	bl, [ptty]	; active_page
   821 000006EB 89DE                    	mov	esi, ebx
   822 000006ED 66D1E6                  	shl 	si, 1
   823 000006F0 81C6[586C0000]          	add	esi, ttychr
   824 000006F6 668B06                  	mov	ax, [esi]
   825                                  	;and	ax, ax
   826                                  	;;jz	short _c8
   827                                  	;jz	short hang
   828                                  	; 24/12/2021
   829 000006F9 21C0                    	and	eax, eax
   830 000006FB 74E5                    	jz	short _hang
   831 000006FD 66C7060000              	mov	word [esi], 0
   832 00000702 80FB03                  	cmp	bl, 3		; Video page 3
   833                                  	;jb	short _c8
   834 00000705 72D9                    	jb	short hang
   835                                  	;	
   836                                  	; 02/09/2014
   837 00000707 B40E                    	mov	ah, 0Eh		; Yellow character 
   838                                  				; on black background
   839                                  	; 24/12/2021 (32 bit reg push-pop)
   840                                  	; 07/09/2014
   841                                  nxtl:
   842 00000709 53                      	push	ebx
   843                                  	;
   844                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   845                                  				; bh = 0 (video mode)
   846                                  				; Retro UNIX 386 v1 - Video Mode 0
   847                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   848 0000070A 50                      	push	eax
   849 0000070B E8780D0000              	call 	write_tty
   850 00000710 58                      	pop	eax
   851                                  	;pop	bx
   852 00000711 5B                      	pop	ebx
   853 00000712 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   854                                  	;jne	short _c8
   855 00000714 75CA                    	jne	short hang
   856 00000716 B00A                    	mov	al, 0Ah		; next line
   857 00000718 EBEF                    	jmp	short nxtl
   858                                  	
   859                                  ;_c8:
   860                                  ;	; 25/08/2014
   861                                  ;	cli			; Disable interrupts
   862                                  ;	mov	al, [scounter + 1]
   863                                  ;	and	al, al
   864                                  ;	jnz	hang
   865                                  ;	call	rtc_p
   866                                  ;	jmp     hang
   867                                  
   868                                  
   869                                  	; 27/08/2014
   870                                  	; 20/08/2014
   871                                  printk:
   872                                          ;mov    edi, [scr_row]
   873                                  pkl:
   874 0000071A AC                      	lodsb
   875 0000071B 08C0                    	or 	al, al
   876 0000071D 7404                    	jz	short pkr
   877 0000071F 66AB                    	stosw
   878 00000721 EBF7                    	jmp	short pkl
   879                                  pkr:
   880 00000723 C3                      	retn
   881                                  
   882                                  ; 25/07/2015
   883                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   884                                  ; 17/02/2015
   885                                  ; 06/02/2015 (unix386.s)
   886                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   887                                  ;
   888                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   889                                  ;
   890                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   891                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   892                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   893                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   894                                  ;									       :
   895                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   896                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   897                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   898                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   899                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   900                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   901                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   902                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   903                                  ;-------------------------------------------------------------------------------
   904                                  ;
   905                                  
   906                                  timer_int:	; IRQ 0
   907                                  ;int_08h:	; Timer
   908                                  	; 14/10/2015
   909                                  	; Here, we are simulating system call entry (for task switch)
   910                                  	; (If multitasking is enabled, 
   911                                  	; 'clock' procedure may jump to 'sysrelease')
   912 00000724 1E                      	push	ds
   913 00000725 06                      	push	es
   914 00000726 0FA0                    	push	fs
   915 00000728 0FA8                    	push	gs
   916 0000072A 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   917 0000072B 66B91000                	mov     cx, KDATA
   918 0000072F 8ED9                            mov     ds, cx
   919 00000731 8EC1                            mov     es, cx
   920 00000733 8EE1                            mov     fs, cx
   921 00000735 8EE9                            mov     gs, cx
   922                                  	;
   923 00000737 0F20D9                  	mov	ecx, cr3
   924 0000073A 890D[D9070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   925                                  	;
   926 00000740 3B0D[286C0000]          	cmp 	ecx, [k_page_dir]
   927 00000746 741F                    	je	short T3
   928                                  	;
   929                                  	; timer interrupt has been occurred while OS is in user mode
   930 00000748 A3[08700000]            	mov 	[u.r0], eax
   931 0000074D 89E1                    	mov	ecx, esp
   932 0000074F 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   933 00000752 890D[00700000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   934 00000758 8925[04700000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   935                                  	;
   936 0000075E 8B0D[286C0000]          	mov	ecx, [k_page_dir]
   937 00000764 0F22D9                  	mov	cr3, ecx
   938                                  T3:
   939 00000767 FB                      	sti				; INTERRUPTS BACK ON
   940 00000768 66FF05[A46C0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   941 0000076F 7507                    	JNZ	short T4		; GO TO TEST_DAY
   942 00000771 66FF05[A66C0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   943                                  T4:					; TEST_DAY
   944 00000778 66833D[A66C0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   945 00000780 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   946 00000782 66813D[A46C0000]B0-     	CMP	word [TIMER_LOW],0B0H
   946 0000078A 00                 
   947 0000078B 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   948                                  
   949                                  ;-----	TIMER HAS GONE 24 HOURS
   950                                  	;;SUB	AX,AX
   951                                  	;MOV	[TIMER_HIGH],AX
   952                                  	;MOV	[TIMER_LOW],AX
   953 0000078D 29C0                    	sub	eax, eax
   954 0000078F A3[A46C0000]            	mov	[TIMER_LH], eax
   955                                  	;	
   956 00000794 C605[A86C0000]01        	MOV	byte [TIMER_OFL],1
   957                                  
   958                                  ;-----	TEST FOR DISKETTE TIME OUT
   959                                  
   960                                  T5:
   961                                  	; 23/12/2014
   962 0000079B EB1D                    	jmp	short T6		; will be replaced with nop, nop
   963                                  					; (9090h) if a floppy disk
   964                                  					; is detected.
   965                                  	;mov	al,[CS:MOTOR_COUNT]
   966 0000079D A0[AB6C0000]            	mov	al, [MOTOR_COUNT]
   967 000007A2 FEC8                    	dec	al
   968                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   969 000007A4 A2[AB6C0000]            	mov	[MOTOR_COUNT], al
   970                                  	;mov	[ORG_MOTOR_COUNT], al
   971 000007A9 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   972 000007AB B0F0                    	mov 	al,0F0h
   973                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   974 000007AD 2005[AA6C0000]          	and	[MOTOR_STATUS], al
   975                                  	;and	[ORG_MOTOR_STATUS], al
   976 000007B3 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   977                                  					; bit 2 = enable controller
   978                                  					;	1 = normal operation
   979                                  					;	0 = reset	
   980                                  					; bit 0, 1 = drive select
   981                                  					; bit 4-7 = motor running bits 
   982 000007B5 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
   983 000007B9 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
   984                                  T6:	
   985                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
   986                                  					; TIMER TICK INTERRUPT
   987                                  	;;inc	word [wait_count] ;;27/02/2015
   988                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
   989                                  	;;;;cli
   990                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
   991 000007BA FF15[D5070000]          	call	[x_timer] ; 14/05/2015
   992                                  T7:
   993                                  	; 14/10/2015
   994 000007C0 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
   995 000007C2 FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
   996 000007C3 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
   997                                  	;
   998 000007C5 A1[D9070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
   999 000007CA 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1000                                  	;
  1001 000007CD 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1002                                  	;
  1003 000007CE 0FA9                    	pop	gs
  1004 000007D0 0FA1                    	pop	fs
  1005 000007D2 07                      	pop	es
  1006 000007D3 1F                      	pop	ds
  1007 000007D4 CF                      	iretd	; return from interrupt
  1008                                  
  1009                                  
  1010                                  ; ////////////////
  1011                                  
  1012                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1013                                  x_timer:
  1014 000007D5 [DD070000]              	dd 	u_timer			; 14/05/2015
  1015                                  	;dd	clock
  1016                                  
  1017                                  ; 14/10/2015
  1018 000007D9 00000000                cr3reg: dd 0
  1019                                  
  1020                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1021                                  	; 06/02/2015
  1022                                  	; 07/09/2014
  1023                                  	; 21/08/2014
  1024                                  u_timer:
  1025                                  ;timer_int:	; IRQ 0
  1026                                  	; 06/02/2015
  1027                                  	;push	eax
  1028                                  	;push	edx
  1029                                  	;push	ecx
  1030                                  	;push	ebx
  1031                                  	;push	ds
  1032                                  	;push	es
  1033                                  	;mov	eax, KDATA
  1034                                  	;mov	ds, ax
  1035                                  	;mov	es, ax
  1036 000007DD FF05[6C6C0000]          	inc	dword [tcount]
  1037 000007E3 BB[B2670000]            	mov	ebx, tcountstr + 4
  1038                                  	;mov	ax, [tcount]
  1039                                  	; 24/12/2021
  1040 000007E8 A1[6C6C0000]            	mov	eax, [tcount]
  1041 000007ED B90A000000              	mov	ecx, 10
  1042                                  rp_divtcnt:
  1043 000007F2 31D2                    	xor	edx, edx
  1044 000007F4 F7F1                    	div	ecx
  1045 000007F6 80C230                  	add	dl, 30h
  1046 000007F9 8813                    	mov	[ebx], dl
  1047                                  	;or	ax, ax
  1048                                  	; 24/12/2021
  1049 000007FB 09C0                    	or	eax, eax
  1050 000007FD 7403                    	jz	short print_lzero
  1051 000007FF 4B                      	dec	ebx
  1052 00000800 EBF0                    	jmp	short rp_divtcnt
  1053                                  print_lzero:
  1054 00000802 81FB[AE670000]          	cmp	ebx, tcountstr
  1055 00000808 7606                    	jna	short print_tcount
  1056 0000080A 4B                      	dec	ebx
  1057 0000080B C60330                   	mov	byte [ebx], 30h
  1058 0000080E EBF2                    	jmp	short print_lzero
  1059                                  print_tcount:
  1060 00000810 56                      	push	esi
  1061 00000811 57                      	push	edi
  1062 00000812 BE[8A670000]            	mov	esi, timer_msg ; Timer interrupt message
  1063                                  	; 07/09/2014
  1064                                  	;mov	bx, 1		; Video page 1
  1065                                  	; 24/12/2021
  1066 00000817 29DB                    	sub	ebx, ebx
  1067 00000819 FEC3                    	inc	bl ; ebx = 1
  1068                                  ptmsg:
  1069 0000081B AC                      	lodsb
  1070 0000081C 08C0                    	or	al, al
  1071 0000081E 740D                    	jz	short ptmsg_ok
  1072 00000820 56                      	push	esi
  1073                                  	;push	bx
  1074                                  	; 24/12/2021
  1075 00000821 53                              push	ebx
  1076 00000822 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1077 00000824 E85F0C0000              	call 	write_tty
  1078                                  	;pop	bx
  1079                                  	; 24/12/2021
  1080 00000829 5B                      	pop	ebx
  1081 0000082A 5E                      	pop	esi
  1082 0000082B EBEE                    	jmp	short ptmsg
  1083                                  	;; 27/08/2014
  1084                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1085                                  	;call	printk
  1086                                  	;
  1087                                  ptmsg_ok:
  1088                                  	; 07/09/2014
  1089                                  	;xor	dx, dx		; column 0, row 0
  1090                                  	; 24/12/2021
  1091 0000082D 31D2                    	xor	edx, edx
  1092 0000082F E8760D0000              	call	set_cpos	; set cursor position to 0,0 
  1093                                  	; 23/02/2015
  1094                                  	; 25/08/2014
  1095                                  	;mov	ebx, scounter		; (seconds counter)
  1096                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1097                                  ;	dec	byte [scounter+1]
  1098                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1099                                  ;	jns	short u_timer_retn
  1100                                  	; 26/02/2015
  1101                                  ;	call	rtc_p
  1102                                  ;	mov	ebx, scounter		; (seconds counter)
  1103                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1104                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1105                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1106                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1107                                  ;	mov	byte [ebx], 5
  1108                                  ;	inc	byte [ebx+1] ; 19
  1109                                  ;;timer_eoi:
  1110                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1111                                  ;;	out	20h, al	; 8259 PORT
  1112                                  	;
  1113                                  ;u_timer_retn:  ; 06/02/2015
  1114 00000834 5F                      	pop	edi
  1115 00000835 5E                      	pop	esi
  1116                                  	;pop	es
  1117                                  	;pop	ds
  1118                                  	;pop	ebx
  1119                                  	;pop	ecx
  1120                                  	;pop	edx
  1121                                  	;pop	eax
  1122                                  	;iret
  1123 00000836 C3                      	retn	; 06/02/2015
  1124                                  
  1125                                  	; 28/08/2014
  1126                                  irq0:
  1127 00000837 6A00                            push 	dword 0
  1128 00000839 EB48                    	jmp	short which_irq
  1129                                  irq1:
  1130 0000083B 6A01                            push 	dword 1
  1131 0000083D EB44                    	jmp	short which_irq
  1132                                  irq2:
  1133 0000083F 6A02                            push 	dword 2
  1134 00000841 EB40                    	jmp	short which_irq
  1135                                  irq3:
  1136                                  	; 20/11/2015
  1137                                  	; 24/10/2015
  1138 00000843 2EFF15[823B0000]        	call	dword [cs:com2_irq3]
  1139 0000084A 6A03                    	push 	dword 3
  1140 0000084C EB35                    	jmp	short which_irq
  1141                                  irq4:
  1142                                  	; 20/11/2015
  1143                                  	; 24/10/2015
  1144 0000084E 2EFF15[7E3B0000]        	call	dword [cs:com1_irq4]
  1145 00000855 6A04                            push 	dword 4
  1146 00000857 EB2A                    	jmp	short which_irq
  1147                                  irq5:
  1148 00000859 6A05                            push 	dword 5
  1149 0000085B EB26                    	jmp	short which_irq
  1150                                  irq6:
  1151 0000085D 6A06                            push 	dword 6
  1152 0000085F EB22                    	jmp	short which_irq
  1153                                  irq7:
  1154 00000861 6A07                            push 	dword 7
  1155 00000863 EB1E                    	jmp	short which_irq
  1156                                  irq8:
  1157 00000865 6A08                            push 	dword 8
  1158 00000867 EB1A                    	jmp	short which_irq
  1159                                  irq9:
  1160 00000869 6A09                            push 	dword 9
  1161 0000086B EB16                    	jmp	short which_irq
  1162                                  irq10:
  1163 0000086D 6A0A                            push 	dword 10
  1164 0000086F EB12                    	jmp	short which_irq
  1165                                  irq11:
  1166 00000871 6A0B                            push 	dword 11
  1167 00000873 EB0E                    	jmp	short which_irq
  1168                                  irq12:
  1169 00000875 6A0C                            push 	dword 12
  1170 00000877 EB0A                    	jmp	short which_irq
  1171                                  irq13:
  1172 00000879 6A0D                            push 	dword 13
  1173 0000087B EB06                    	jmp	short which_irq
  1174                                  irq14:
  1175 0000087D 6A0E                            push 	dword 14
  1176 0000087F EB02                    	jmp	short which_irq
  1177                                  irq15:
  1178 00000881 6A0F                            push 	dword 15
  1179                                  	;jmp	short which_irq
  1180                                  
  1181                                  	; 19/10/2015
  1182                                  	; 29/08/2014
  1183                                  	; 21/08/2014
  1184                                  which_irq:
  1185 00000883 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1186 00000886 53                      	push	ebx
  1187 00000887 56                      	push	esi
  1188 00000888 57                      	push	edi
  1189 00000889 1E                      	push 	ds
  1190 0000088A 06                      	push 	es
  1191                                  	;
  1192 0000088B 88C3                    	mov	bl, al
  1193                                  	;
  1194 0000088D B810000000              	mov	eax, KDATA
  1195 00000892 8ED8                    	mov	ds, ax
  1196 00000894 8EC0                    	mov	es, ax
  1197                                  	; 19/10/2015
  1198 00000896 FC                      	cld
  1199                                          ; 27/08/2014
  1200 00000897 8105[38670000]A000-             add     dword [scr_row], 0A0h
  1200 0000089F 0000               
  1201                                  	;
  1202 000008A1 B417                    	mov	ah, 17h	; blue (1) background, 
  1203                                  			; light gray (7) forecolor
  1204 000008A3 8B3D[38670000]                  mov     edi, [scr_row]
  1205 000008A9 B049                    	mov	al, 'I'
  1206 000008AB 66AB                    	stosw
  1207 000008AD B052                    	mov	al, 'R'
  1208 000008AF 66AB                    	stosw
  1209 000008B1 B051                    	mov	al, 'Q'
  1210 000008B3 66AB                    	stosw
  1211 000008B5 B020                    	mov	al, ' '
  1212 000008B7 66AB                    	stosw
  1213 000008B9 88D8                    	mov	al, bl
  1214 000008BB 3C0A                    	cmp	al, 10
  1215 000008BD 7208                    	jb	short iix
  1216 000008BF B031                    	mov	al, '1'
  1217 000008C1 66AB                    	stosw
  1218 000008C3 88D8                    	mov	al, bl
  1219 000008C5 2C0A                    	sub	al, 10
  1220                                  iix:
  1221 000008C7 0430                    	add	al, '0'
  1222 000008C9 66AB                    	stosw
  1223 000008CB B020                    	mov	al, ' '
  1224 000008CD 66AB                    	stosw
  1225 000008CF B021                    	mov	al, '!'
  1226 000008D1 66AB                    	stosw
  1227 000008D3 B020                    	mov	al, ' '
  1228 000008D5 66AB                    	stosw
  1229                                  	; 23/02/2015
  1230 000008D7 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1231 000008DA 0F868D010000            	jna	iiret
  1232 000008E0 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1233 000008E2 E6A0                    	out	0A0h, al ; the 2nd 8259
  1234 000008E4 E984010000              	jmp     iiret
  1235                                  	;
  1236                                  	; 22/08/2014
  1237                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1238                                  	;out	20h, al	; 8259 PORT
  1239                                  	;
  1240                                  	;pop	es
  1241                                  	;pop	ds
  1242                                  	;pop	edi
  1243                                  	;pop	esi
  1244                                  	;pop	ebx
  1245                                  	;pop 	eax
  1246                                  	;iret
  1247                                  
  1248                                  	; 02/04/2015
  1249                                  	; 25/08/2014
  1250                                  exc0:
  1251 000008E9 6A00                            push 	dword 0
  1252 000008EB E990000000                      jmp     cpu_except
  1253                                  exc1:
  1254 000008F0 6A01                            push 	dword 1
  1255 000008F2 E989000000                      jmp     cpu_except
  1256                                  exc2:
  1257 000008F7 6A02                            push 	dword 2
  1258 000008F9 E982000000                      jmp     cpu_except
  1259                                  exc3:
  1260 000008FE 6A03                            push 	dword 3
  1261 00000900 EB7E                            jmp     cpu_except
  1262                                  exc4:
  1263 00000902 6A04                            push 	dword 4
  1264 00000904 EB7A                            jmp     cpu_except
  1265                                  exc5:
  1266 00000906 6A05                            push 	dword 5
  1267 00000908 EB76                            jmp     cpu_except
  1268                                  exc6:
  1269 0000090A 6A06                            push 	dword 6
  1270 0000090C EB72                            jmp     cpu_except
  1271                                  exc7:
  1272 0000090E 6A07                            push 	dword 7
  1273 00000910 EB6E                            jmp     cpu_except
  1274                                  exc8:
  1275                                  	; [esp] = Error code
  1276 00000912 6A08                            push 	dword 8
  1277 00000914 EB5C                            jmp     cpu_except_en
  1278                                  exc9:
  1279 00000916 6A09                            push 	dword 9
  1280 00000918 EB66                            jmp     cpu_except
  1281                                  exc10:
  1282                                  	; [esp] = Error code
  1283 0000091A 6A0A                            push 	dword 10
  1284 0000091C EB54                            jmp     cpu_except_en
  1285                                  exc11:
  1286                                  	; [esp] = Error code
  1287 0000091E 6A0B                            push 	dword 11
  1288 00000920 EB50                            jmp     cpu_except_en
  1289                                  exc12:
  1290                                  	; [esp] = Error code
  1291 00000922 6A0C                            push 	dword 12
  1292 00000924 EB4C                            jmp     cpu_except_en
  1293                                  exc13:
  1294                                  	; [esp] = Error code
  1295 00000926 6A0D                            push 	dword 13
  1296 00000928 EB48                            jmp     cpu_except_en
  1297                                  exc14:
  1298                                  	; [esp] = Error code
  1299 0000092A 6A0E                            push 	dword 14
  1300 0000092C EB44                    	jmp	short cpu_except_en
  1301                                  exc15:
  1302 0000092E 6A0F                            push 	dword 15
  1303 00000930 EB4E                            jmp     cpu_except
  1304                                  exc16:
  1305 00000932 6A10                            push 	dword 16
  1306 00000934 EB4A                            jmp     cpu_except
  1307                                  exc17:
  1308                                  	; [esp] = Error code
  1309 00000936 6A11                            push 	dword 17
  1310 00000938 EB38                    	jmp	short cpu_except_en
  1311                                  exc18:
  1312 0000093A 6A12                            push 	dword 18
  1313 0000093C EB42                    	jmp	short cpu_except
  1314                                  exc19:
  1315 0000093E 6A13                            push 	dword 19
  1316 00000940 EB3E                    	jmp	short cpu_except
  1317                                  exc20:
  1318 00000942 6A14                            push 	dword 20
  1319 00000944 EB3A                    	jmp	short cpu_except
  1320                                  exc21:
  1321 00000946 6A15                            push 	dword 21
  1322 00000948 EB36                    	jmp	short cpu_except
  1323                                  exc22:
  1324 0000094A 6A16                            push 	dword 22
  1325 0000094C EB32                    	jmp	short cpu_except
  1326                                  exc23:
  1327 0000094E 6A17                            push 	dword 23
  1328 00000950 EB2E                    	jmp	short cpu_except
  1329                                  exc24:
  1330 00000952 6A18                            push 	dword 24
  1331 00000954 EB2A                    	jmp	short cpu_except
  1332                                  exc25:
  1333 00000956 6A19                            push 	dword 25
  1334 00000958 EB26                    	jmp	short cpu_except
  1335                                  exc26:
  1336 0000095A 6A1A                            push 	dword 26
  1337 0000095C EB22                    	jmp	short cpu_except
  1338                                  exc27:
  1339 0000095E 6A1B                            push 	dword 27
  1340 00000960 EB1E                    	jmp	short cpu_except
  1341                                  exc28:
  1342 00000962 6A1C                            push 	dword 28
  1343 00000964 EB1A                    	jmp	short cpu_except
  1344                                  exc29:
  1345 00000966 6A1D                            push 	dword 29
  1346 00000968 EB16                    	jmp	short cpu_except
  1347                                  exc30:
  1348 0000096A 6A1E                            push 	dword 30
  1349 0000096C EB04                    	jmp	short cpu_except_en
  1350                                  exc31:
  1351 0000096E 6A1F                            push 	dword 31
  1352 00000970 EB0E                            jmp     short cpu_except
  1353                                  
  1354                                  	; 19/10/2015
  1355                                  	; 19/09/2015
  1356                                  	; 01/09/2015
  1357                                  	; 28/08/2015
  1358                                  	; 28/08/2014
  1359                                  cpu_except_en:
  1360 00000972 87442404                	xchg	eax, [esp+4] ; Error code
  1361 00000976 36A3[D0800000]          	mov	[ss:error_code], eax
  1362 0000097C 58                      	pop	eax  ; Exception number
  1363 0000097D 870424                  	xchg	eax, [esp]
  1364                                  		; eax = eax before exception
  1365                                  		; [esp] -> exception number
  1366                                  		; [esp+4] -> EIP to return
  1367                                  	; 19/10/2015
  1368                                  	; 19/09/2015
  1369                                  	; 01/09/2015
  1370                                  	; 28/08/2015
  1371                                  	; 29/08/2014
  1372                                  	; 28/08/2014
  1373                                  	; 25/08/2014
  1374                                  	; 21/08/2014
  1375                                  cpu_except:	; CPU Exceptions
  1376 00000980 FC                      	cld
  1377 00000981 870424                  	xchg	eax, [esp] 
  1378                                  		; eax = Exception number
  1379                                  		; [esp] = eax (before exception)	
  1380 00000984 53                      	push	ebx
  1381 00000985 56                      	push	esi
  1382 00000986 57                      	push	edi
  1383 00000987 1E                      	push 	ds
  1384 00000988 06                      	push 	es
  1385                                  	; 28/08/2015
  1386 00000989 66BB1000                	mov	bx, KDATA
  1387 0000098D 8EDB                    	mov	ds, bx
  1388 0000098F 8EC3                    	mov	es, bx
  1389 00000991 0F20DB                  	mov	ebx, cr3
  1390 00000994 53                      	push	ebx ; (*) page directory
  1391                                  	; 19/10/2015
  1392 00000995 FC                      	cld
  1393                                  	; 25/03/2015
  1394 00000996 8B1D[286C0000]          	mov	ebx, [k_page_dir]
  1395 0000099C 0F22DB                  	mov	cr3, ebx
  1396                                  	; 28/08/2015
  1397 0000099F 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1398 000009A2 7512                    	jne	short cpu_except_nfp
  1399 000009A4 E844280000              	call	page_fault_handler
  1400 000009A9 21C0                    	and 	eax, eax
  1401 000009AB 0F84B8000000                    jz	iiretp ; 01/09/2015
  1402 000009B1 B80E000000              	mov	eax, 0Eh ; 14
  1403                                  cpu_except_nfp:
  1404                                  	; 02/04/2015
  1405 000009B6 BB[E0060000]            	mov	ebx, hang
  1406 000009BB 875C241C                	xchg	ebx, [esp+28]
  1407                                  		; EIP (points to instruction which faults)
  1408                                  	  	; New EIP (hang)
  1409 000009BF 891D[D4800000]          	mov	[FaultOffset], ebx
  1410 000009C5 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1411 000009CD 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1412                                  	;
  1413 000009D5 88C4                    	mov	ah, al
  1414 000009D7 240F                    	and	al, 0Fh
  1415 000009D9 3C09                    	cmp	al, 9
  1416 000009DB 7602                    	jna	short h1ok
  1417 000009DD 0407                    	add	al, 'A'-':'
  1418                                  h1ok:
  1419 000009DF D0EC                    	shr	ah, 1
  1420 000009E1 D0EC                    	shr	ah, 1
  1421 000009E3 D0EC                    	shr	ah, 1
  1422 000009E5 D0EC                    	shr	ah, 1
  1423 000009E7 80FC09                  	cmp	ah, 9
  1424 000009EA 7603                    	jna	short h2ok
  1425 000009EC 80C407                  	add	ah, 'A'-':'
  1426                                  h2ok:	
  1427 000009EF 86E0                    	xchg 	ah, al	
  1428 000009F1 66053030                	add	ax, '00'
  1429 000009F5 66A3[C6670000]          	mov	[excnstr], ax
  1430                                  	;
  1431                                  	; 29/08/2014
  1432 000009FB A1[D4800000]            	mov	eax, [FaultOffset]
  1433 00000A00 51                      	push	ecx
  1434 00000A01 52                      	push	edx
  1435 00000A02 89E3                    	mov	ebx, esp
  1436                                  	; 28/08/2015
  1437 00000A04 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1438                                  			  ; to hexadecimal string
  1439                                  	;mov	ecx, 10	    ; divisor to convert	
  1440                                  			    ; binary number to decimal string
  1441                                  b2d1:
  1442 00000A09 31D2                    	xor	edx, edx
  1443 00000A0B F7F1                    	div	ecx
  1444 00000A0D 6652                    	push	dx
  1445 00000A0F 39C8                    	cmp	eax, ecx
  1446 00000A11 73F6                    	jnb	short b2d1
  1447 00000A13 BF[D1670000]            	mov	edi, EIPstr ; EIP value
  1448                                  			    ; points to instruction which faults	
  1449                                  	; 28/08/2015
  1450 00000A18 89C2                    	mov	edx, eax
  1451                                  b2d2:
  1452                                  	;add	al, '0'
  1453 00000A1A 8A82[88180000]          	mov	al, [edx+hexchrs]
  1454 00000A20 AA                      	stosb		    ; write hexadecimal digit to its place	
  1455 00000A21 39E3                    	cmp	ebx, esp
  1456 00000A23 7606                    	jna	short b2d3
  1457 00000A25 6658                    	pop	ax
  1458 00000A27 88C2                    	mov	dl, al
  1459 00000A29 EBEF                    	jmp	short b2d2
  1460                                  b2d3:
  1461 00000A2B B068                    	mov 	al, 'h' ; 28/08/2015
  1462 00000A2D AA                      	stosb
  1463 00000A2E B020                    	mov	al, 20h	    ; space
  1464 00000A30 AA                      	stosb
  1465 00000A31 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1466 00000A33 AA                      	stosb
  1467                                  	;
  1468 00000A34 5A                      	pop	edx
  1469 00000A35 59                      	pop	ecx
  1470                                  	;
  1471 00000A36 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1472                                  			; white (F) forecolor
  1473 00000A38 BE[B6670000]            	mov	esi, exc_msg ; message offset
  1474                                  	;
  1475 00000A3D EB11                    	jmp	short piemsg
  1476                                  	;
  1477                                          ;add    dword [scr_row], 0A0h
  1478                                          ;mov    edi, [scr_row]
  1479                                          ;
  1480                                  	;call 	printk
  1481                                  	;
  1482                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1483                                  	;out	20h, al	; 8259 PORT
  1484                                  	;
  1485                                  	;pop	es
  1486                                  	;pop	ds
  1487                                  	;pop	edi
  1488                                  	;pop	esi
  1489                                  	;pop 	eax
  1490                                  	;iret
  1491                                  	
  1492                                  	; 28/08/2015
  1493                                  	; 23/02/2015
  1494                                  	; 20/08/2014
  1495                                  ignore_int:
  1496 00000A3F 50                      	push	eax
  1497 00000A40 53                      	push	ebx ; 23/02/2015
  1498 00000A41 56                      	push	esi
  1499 00000A42 57                      	push	edi
  1500 00000A43 1E                      	push 	ds
  1501 00000A44 06                      	push 	es
  1502                                  	; 28/08/2015
  1503 00000A45 0F20D8                  	mov	eax, cr3
  1504 00000A48 50                      	push	eax ; (*) page directory
  1505                                  	;
  1506 00000A49 B467                    	mov	ah, 67h	; brown (6) background, 
  1507                                  			; light gray (7) forecolor
  1508 00000A4B BE[74670000]            	mov	esi, int_msg ; message offset
  1509                                  piemsg:
  1510                                          ; 27/08/2014
  1511 00000A50 8105[38670000]A000-             add     dword [scr_row], 0A0h
  1511 00000A58 0000               
  1512 00000A5A 8B3D[38670000]                  mov     edi, [scr_row]
  1513                                          ;
  1514 00000A60 E8B5FCFFFF              	call 	printk
  1515                                  	;
  1516                                  	; 23/02/2015
  1517 00000A65 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1518 00000A67 E6A0                    	out	0A0h, al ; the 2nd 8259
  1519                                  iiretp: ; 01/09/2015
  1520                                  	; 28/08/2015
  1521 00000A69 58                      	pop	eax ; (*) page directory
  1522 00000A6A 0F22D8                  	mov	cr3, eax
  1523                                  	;
  1524                                  iiret:
  1525                                  	; 22/08/2014
  1526 00000A6D B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1527 00000A6F E620                    	out	20h, al	; 8259 PORT
  1528                                  	;
  1529 00000A71 07                      	pop	es
  1530 00000A72 1F                      	pop	ds
  1531 00000A73 5F                      	pop	edi
  1532 00000A74 5E                      	pop	esi
  1533 00000A75 5B                      	pop	ebx ; 29/08/2014
  1534 00000A76 58                      	pop 	eax
  1535 00000A77 CF                      	iretd
  1536                                  
  1537                                  	; 26/02/2015
  1538                                  	; 07/09/2014
  1539                                  	; 25/08/2014
  1540                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1541                                  	; 22/08/2014
  1542 00000A78 50                      	push	eax
  1543 00000A79 53                      	push	ebx ; 29/08/2014
  1544 00000A7A 56                      	push	esi
  1545 00000A7B 57                      	push	edi
  1546 00000A7C 1E                      	push 	ds
  1547 00000A7D 06                      	push 	es
  1548                                  	;
  1549 00000A7E B810000000              	mov	eax, KDATA
  1550 00000A83 8ED8                    	mov	ds, ax
  1551 00000A85 8EC0                    	mov	es, ax
  1552                                  	;
  1553                                  	; 25/08/2014
  1554 00000A87 E884000000              	call	rtc_p
  1555                                  	;
  1556                                  	; 22/02/2015 - dsectpm.s
  1557                                  	; [ source: http://wiki.osdev.org/RTC ]
  1558                                  	; read status register C to complete procedure
  1559                                  	;(it is needed to get a next IRQ 8) 
  1560 00000A8C B00C                    	mov	al, 0Ch ; 
  1561 00000A8E E670                    	out	70h, al ; select register C
  1562 00000A90 90                      	nop
  1563 00000A91 E471                    	in	al, 71h ; just throw away contents
  1564                                  	; 22/02/2015
  1565 00000A93 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1566 00000A95 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1567                                  	;
  1568 00000A97 EBD4                    	jmp	short iiret	
  1569                                  
  1570                                  	; 22/08/2014
  1571                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1572                                  	; (INT 1Ah)
  1573                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1574                                  time_of_day:
  1575 00000A99 E862010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1576 00000A9E 726F                            jc      short rtc_retn 
  1577 00000AA0 B000                    	mov	al, CMOS_SECONDS
  1578 00000AA2 E843010000              	call	CMOS_READ
  1579 00000AA7 A2[9C6C0000]            	mov	[time_seconds], al 
  1580 00000AAC B002                    	mov	al, CMOS_MINUTES
  1581 00000AAE E837010000              	call	CMOS_READ
  1582 00000AB3 A2[9D6C0000]            	mov	[time_minutes], al 
  1583 00000AB8 B004                    	mov	al, CMOS_HOURS
  1584 00000ABA E82B010000              	call	CMOS_READ
  1585 00000ABF A2[9E6C0000]                    mov     [time_hours], al
  1586 00000AC4 B006                    	mov	al, CMOS_DAY_WEEK 
  1587 00000AC6 E81F010000              	call	CMOS_READ
  1588 00000ACB A2[9F6C0000]            	mov	[date_wday], al
  1589 00000AD0 B007                     	mov	al, CMOS_DAY_MONTH
  1590 00000AD2 E813010000              	call	CMOS_READ
  1591 00000AD7 A2[A06C0000]            	mov	[date_day], al
  1592 00000ADC B008                    	mov	al, CMOS_MONTH
  1593 00000ADE E807010000              	call	CMOS_READ
  1594 00000AE3 A2[A16C0000]            	mov	[date_month], al
  1595 00000AE8 B009                    	mov	al, CMOS_YEAR
  1596 00000AEA E8FB000000              	call	CMOS_READ
  1597 00000AEF A2[A26C0000]            	mov	[date_year], al
  1598 00000AF4 B032                    	mov	al, CMOS_CENTURY
  1599 00000AF6 E8EF000000              	call	CMOS_READ
  1600 00000AFB A2[A36C0000]            	mov	[date_century], al
  1601                                  	;
  1602 00000B00 B000                    	mov	al, CMOS_SECONDS
  1603 00000B02 E8E3000000              	call 	CMOS_READ
  1604 00000B07 3A05[9C6C0000]          	cmp	al, [time_seconds]
  1605 00000B0D 758A                    	jne	short time_of_day
  1606                                  
  1607                                  rtc_retn:
  1608 00000B0F C3                      	retn
  1609                                  
  1610                                  rtc_p:	
  1611                                  	; 07/09/2014
  1612                                  	; 29/08/2014
  1613                                  	; 27/08/2014
  1614                                  	; 25/08/2014
  1615                                   	; Print Real Time Clock content
  1616                                  	;
  1617                                  	;
  1618 00000B10 E884FFFFFF              	call	time_of_day
  1619 00000B15 72F8                    	jc	short rtc_retn
  1620                                  	;
  1621 00000B17 3A05[28680000]          	cmp	al, [ptime_seconds]
  1622 00000B1D 74F0                            je      short rtc_retn ; 29/08/2014
  1623                                  	;
  1624 00000B1F A2[28680000]            	mov	[ptime_seconds], al
  1625                                  	;
  1626 00000B24 A0[A36C0000]            	mov	al, [date_century]
  1627 00000B29 E8ED000000              	call	bcd_to_ascii
  1628 00000B2E 66A3[F5670000]          	mov	[datestr+6], ax
  1629 00000B34 A0[A26C0000]            	mov	al, [date_year]
  1630 00000B39 E8DD000000              	call	bcd_to_ascii
  1631 00000B3E 66A3[F7670000]          	mov	[datestr+8], ax
  1632 00000B44 A0[A16C0000]            	mov	al, [date_month]
  1633 00000B49 E8CD000000              	call	bcd_to_ascii
  1634 00000B4E 66A3[F2670000]          	mov	[datestr+3], ax
  1635 00000B54 A0[A06C0000]            	mov	al, [date_day]
  1636 00000B59 E8BD000000              	call	bcd_to_ascii
  1637 00000B5E 66A3[EF670000]          	mov	[datestr], ax
  1638                                  	;
  1639 00000B64 0FB61D[9F6C0000]        	movzx	ebx, byte [date_wday]
  1640 00000B6B C0E302                  	shl 	bl, 2
  1641 00000B6E 81C3[08680000]          	add	ebx, daytmp
  1642 00000B74 8B03                    	mov	eax, [ebx]
  1643 00000B76 A3[FA670000]            	mov	[daystr], eax
  1644                                  	;
  1645 00000B7B A0[9E6C0000]            	mov	al, [time_hours]
  1646 00000B80 E896000000              	call	bcd_to_ascii
  1647 00000B85 66A3[FE670000]          	mov	[timestr], ax
  1648 00000B8B A0[9D6C0000]            	mov	al, [time_minutes]
  1649 00000B90 E886000000              	call	bcd_to_ascii
  1650 00000B95 66A3[01680000]          	mov	[timestr+3], ax
  1651 00000B9B A0[9C6C0000]            	mov	al, [time_seconds]
  1652 00000BA0 E876000000              	call	bcd_to_ascii
  1653 00000BA5 66A3[04680000]          	mov	[timestr+6], ax
  1654                                  	;		
  1655 00000BAB BE[DD670000]            	mov	esi, rtc_msg ; message offset
  1656                                  	; 23/02/2015
  1657 00000BB0 52                      	push	edx
  1658 00000BB1 51                      	push	ecx
  1659                                  	; 07/09/2014
  1660 00000BB2 66BB0200                	mov	bx, 2		; Video page 2
  1661                                  prtmsg:
  1662 00000BB6 AC                      	lodsb
  1663 00000BB7 08C0                    	or	al, al
  1664 00000BB9 740F                    	jz	short prtmsg_ok
  1665 00000BBB 56                      	push	esi
  1666 00000BBC 6653                    	push	bx
  1667 00000BBE B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1668                                  			; white (F) forecolor
  1669 00000BC0 E8C3080000              	call 	write_tty
  1670 00000BC5 665B                    	pop	bx
  1671 00000BC7 5E                      	pop	esi
  1672 00000BC8 EBEC                    	jmp	short prtmsg
  1673                                  	;
  1674                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1675                                  	;call	printk
  1676                                  prtmsg_ok:
  1677                                  	; 07/09/2014
  1678 00000BCA 6631D2                  	xor	dx, dx		; column 0, row 0
  1679 00000BCD E8D8090000              	call	set_cpos	; set curspor position to 0,0 
  1680                                  	; 23/02/2015
  1681 00000BD2 59                      	pop	ecx
  1682 00000BD3 5A                      	pop	edx
  1683 00000BD4 C3                      	retn
  1684                                  
  1685                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1686                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1687                                  default_irq7:
  1688                                  	; 24/12/2021
  1689                                  	;push	ax
  1690 00000BD5 50                      	push	eax
  1691 00000BD6 B00B                    	mov	al, 0Bh  ; In-Service register
  1692 00000BD8 E620                    	out	20h, al
  1693 00000BDA EB00                            jmp short $+2
  1694 00000BDC EB00                    	jmp short $+2
  1695 00000BDE E420                    	in	al, 20h
  1696 00000BE0 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1697 00000BE2 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1698 00000BE4 B020                            mov     al, 20h ; EOI
  1699 00000BE6 E620                    	out	20h, al 
  1700                                  irq7_iret:
  1701                                  	;pop	ax
  1702                                  	; 24/12/2021
  1703 00000BE8 58                      	pop	eax
  1704 00000BE9 CF                      	iretd	
  1705                                  	
  1706                                  	; 24/12/2021
  1707                                  	; 22/08/2014
  1708                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1709                                  CMOS_READ:
  1710 00000BEA 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1711 00000BEB D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1712 00000BED F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1713 00000BEE D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1714 00000BF0 FA                      	cli		; DISABLE INTERRUPTS
  1715 00000BF1 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1716 00000BF3 90                      	nop		; I/O DELAY
  1717 00000BF4 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1718                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1719                                  	; 24/12/2021
  1720 00000BF6 50                      	push	eax
  1721                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1722                                  		     ; ----- 10/06/85 (test4.asm)
  1723 00000BF7 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1724                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1725 00000BF9 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1726 00000BFB E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1727                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1728                                  	; 24/12/2021
  1729 00000BFD 58                      	pop	eax
  1730 00000BFE 9D                      	popf	
  1731 00000BFF C3                      	retn		; RETURN WITH FLAGS RESTORED
  1732                                  
  1733                                  	; 22/08/2014
  1734                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1735                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1736 00000C00 51                      	push	ecx
  1737 00000C01 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1738                                  		; mov cx, 800	
  1739                                  UPD_10:
  1740 00000C06 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1741 00000C08 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1742 00000C09 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1743 00000C0E A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1744 00000C10 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1745 00000C12 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1746 00000C13 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1747 00000C15 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1748                                  		; xor ax, ax
  1749 00000C17 F9                      	stc				; SET CARRY FOR ERROR
  1750                                  UPD_90:
  1751 00000C18 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1752 00000C19 FA                      	cli				; INTERRUPTS OFF DURING SET
  1753 00000C1A C3                      	retn				; RETURN WITH CY FLAG SET
  1754                                  
  1755                                  bcd_to_ascii:
  1756                                  	; 25/08/2014
  1757                                  	; INPUT ->
  1758                                  	;	al = Packed BCD number
  1759                                  	; OUTPUT ->
  1760                                  	;	ax  = ASCII word/number
  1761                                  	;
  1762                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1763                                  	;
  1764 00000C1B D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1765                                  					; AH = AL / 10h
  1766                                  					; AL = AL MOD 10h
  1767 00000C1D 660D3030                	or ax,'00'                      ; Make it ASCII based
  1768                                  
  1769 00000C21 86E0                            xchg ah, al 
  1770                                  	
  1771 00000C23 C3                      	retn	
  1772                                  	
  1773                                  
  1774                                  %include 'keyboard.inc' ; 07/03/2015
  1775                              <1> ; Retro UNIX 386 v1.1 Kernel - KEYBOARD.INC
  1776                              <1> ; Last Modification: 24/12/2021
  1777                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1778                              <1> ;
  1779                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1780                              <1> 
  1781                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  1782                              <1> ; 30/06/2015
  1783                              <1> ; 11/03/2015
  1784                              <1> ; 28/02/2015
  1785                              <1> ; 25/02/2015
  1786                              <1> ; 20/02/2015
  1787                              <1> ; 18/02/2015
  1788                              <1> ; 03/12/2014
  1789                              <1> ; 07/09/2014
  1790                              <1> ; KEYBOARD INTERRUPT HANDLER
  1791                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1792                              <1> 
  1793                              <1> ;getch:
  1794                              <1> ;	; 18/02/2015
  1795                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1796                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1797                              <1> ;	; routine, later... (multi tasking ability)
  1798                              <1> ;	; 28/02/2015
  1799                              <1> ;	sti	; enable interrupts
  1800                              <1> ;	;
  1801                              <1> ;	;push	esi
  1802                              <1> ;	;push	ebx
  1803                              <1> ;	;xor	ebx, ebx
  1804                              <1> ;	;mov	bl, [ptty]  ; active_page
  1805                              <1> ;	;mov	esi, ebx
  1806                              <1> ;	;shl 	si, 1
  1807                              <1> ;	;add	esi, ttychr
  1808                              <1> ;getch_1:
  1809                              <1> ;	;mov	ax, [esi]
  1810                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1811                              <1> ;	and	ax, ax
  1812                              <1> ;	jz	short getch_2
  1813                              <1> ;	mov	word [ttychr], 0
  1814                              <1> ;	;mov	word [esi], 0
  1815                              <1> ;	;pop	ebx
  1816                              <1> ;	;pop	esi
  1817                              <1> ;	retn
  1818                              <1> ;getch_2:
  1819                              <1> ;	hlt	; not proper for multi tasking!
  1820                              <1> ;		; (temporary halt for now)
  1821                              <1> ;		; 'sleep' on tty 
  1822                              <1> ;		; will (must) be located here		
  1823                              <1> ;	nop
  1824                              <1> ;	jmp	short getch_1
  1825                              <1> 
  1826                              <1> keyb_int:
  1827                              <1> 	; 30/06/2015
  1828                              <1> 	; 25/02/2015
  1829                              <1> 	; 20/02/2015
  1830                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1831                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1832                              <1> 	; 30/06/2014
  1833                              <1> 	; 10/05/2013	
  1834                              <1>       	; Retro Unix 8086 v1 feature only!
  1835                              <1> 	; 03/03/2014
  1836                              <1> 	
  1837 00000C24 1E                  <1> 	push	ds
  1838 00000C25 53                  <1> 	push	ebx
  1839 00000C26 50                  <1> 	push	eax
  1840                              <1> 	;
  1841 00000C27 66B81000            <1> 	mov	ax, KDATA
  1842 00000C2B 8ED8                <1> 	mov	ds, ax
  1843                              <1> 	;
  1844 00000C2D 9C                  <1> 	pushfd
  1845 00000C2E 0E                  <1> 	push	cs
  1846 00000C2F E812020000          <1> 	call	kb_int  ; int_09h
  1847                              <1> 	;
  1848 00000C34 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1849                              <1> 	;call	getc
  1850 00000C36 E856000000          <1> 	call	int_16h ; 30/06/2015
  1851 00000C3B 7450                <1> 	jz	short keyb_int4
  1852                              <1> 	;
  1853 00000C3D B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1854                              <1> 	;call	getc
  1855 00000C3F E84D000000          <1> 	call	int_16h ; 30/06/2015
  1856                              <1> 	;
  1857                              <1> 	; 20/02/2015
  1858 00000C44 0FB61D[566C0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1859                              <1> 	;
  1860 00000C4B 20C0                <1> 	and 	al, al
  1861 00000C4D 751E                <1> 	jnz	short keyb_int1
  1862                              <1> 	;
  1863 00000C4F 80FC68              <1> 	cmp	ah, 68h	; ALT + F1 key
  1864 00000C52 7219                <1> 	jb	short keyb_int1
  1865 00000C54 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1866 00000C57 7714                <1> 	ja	short keyb_int1
  1867                              <1> 	;
  1868 00000C59 88D8                <1> 	mov	al, bl
  1869 00000C5B 0468                <1> 	add	al, 68h
  1870 00000C5D 38E0                <1> 	cmp	al, ah
  1871 00000C5F 7409                <1> 	je	short keyb_int0
  1872 00000C61 88E0                <1> 	mov	al, ah
  1873 00000C63 2C68                <1> 	sub	al, 68h
  1874 00000C65 E8FB0A0000          <1> 	call	tty_sw
  1875                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1876                              <1> keyb_int0: ; 30/06/2015
  1877 00000C6A 6631C0              <1> 	xor	ax, ax
  1878                              <1> keyb_int1:
  1879 00000C6D D0E3                <1> 	shl	bl, 1
  1880 00000C6F 81C3[586C0000]      <1> 	add	ebx, ttychr
  1881                              <1> 	;
  1882 00000C75 6609C0              <1> 	or	ax, ax
  1883 00000C78 7406                <1> 	jz	short keyb_int2
  1884                              <1> 	;
  1885 00000C7A 66833B00            <1> 	cmp 	word [ebx], 0
  1886 00000C7E 7703                <1>         ja      short keyb_int3 
  1887                              <1> keyb_int2:
  1888 00000C80 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1889                              <1> 			   ; and scan code of the character
  1890                              <1> 			   ; for current tty (or last tty
  1891                              <1> 			   ; just before tty switch).
  1892                              <1> keyb_int3:
  1893 00000C83 A0[566C0000]        <1>         mov     al, [ptty]
  1894 00000C88 E81F440000          <1> 	call	wakeup
  1895                              <1> 	;
  1896                              <1> keyb_int4:
  1897 00000C8D 58                  <1> 	pop	eax
  1898 00000C8E 5B                  <1> 	pop	ebx
  1899 00000C8F 1F                  <1> 	pop	ds
  1900 00000C90 CF                  <1> 	iret
  1901                              <1> 
  1902                              <1> ; 18/02/2015
  1903                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1904                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1905                              <1> ; scancode and ascii code of the character 
  1906                              <1> ; in the tty input (ttychr) buffer. 
  1907                              <1> ; Test procedures must call 'getch' for tty input
  1908                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1909                              <1> ; due to infinite (key press) waiting loop.
  1910                              <1> ; 
  1911                              <1> ; 03/12/2014
  1912                              <1> ; 26/08/2014
  1913                              <1> ; KEYBOARD I/O
  1914                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1915                              <1> 
  1916                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1917                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1918                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1919                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1920                              <1> 
  1921                              <1> int_16h: ; 30/06/2015
  1922                              <1> ;getc:
  1923 00000C91 9C                  <1> 	pushfd	; 28/08/2014
  1924 00000C92 0E                  <1> 	push 	cs
  1925 00000C93 E826000000          <1> 	call 	getc_int
  1926 00000C98 C3                  <1> 	retn
  1927                              <1> 
  1928                              <1> ; 24/12/2021
  1929                              <1> 
  1930                              <1> 	;-----	SHIFT STATUS
  1931                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  1932 00000C99 8A25[14660000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  1933 00000C9F 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  1934                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  1935                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  1936 00000CA2 C0E405              <1>         shl	ah, 5
  1937 00000CA5 A0[14660000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  1938 00000CAA 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  1939 00000CAC 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  1940 00000CAE A0[16660000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  1941 00000CB3 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  1942 00000CB5 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  1943                              <1> _K3:
  1944 00000CB7 A0[13660000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  1945 00000CBC EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  1946                              <1> 
  1947                              <1> getc_int:
  1948                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  1949                              <1> 	; 28/02/2015
  1950                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  1951                              <1> 	;	      instead of pc-at bios - 1985-)
  1952                              <1> 	; 28/08/2014 (_k1d)
  1953                              <1> 	; 30/06/2014
  1954                              <1> 	; 03/03/2014
  1955                              <1> 	; 28/02/2014
  1956                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  1957                              <1> 	; rombios source code (21/04/1986)
  1958                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  1959                              <1> 	;
  1960                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  1961                              <1> 	;
  1962                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  1963                              <1> 	; KEYBOARD I/O								      :
  1964                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  1965                              <1> 	; INPUT									      :
  1966                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  1967                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  1968                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  1969                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  1970                              <1> 	;-----------------------------------------------------------------------------:
  1971                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  1972                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  1973                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  1974                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  1975                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  1976                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  1977                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  1978                              <1> 	;-----------------------------------------------------------------------------:	
  1979                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  1980                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  1981                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  1982                              <1> 	;-----------------------------------------------------------------------------:	
  1983                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  1984                              <1> 	;	      (AL) = 05H                                                      :
  1985                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  1986                              <1> 	;		       							      :
  1987                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  1988                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  1989                              <1> 	;                     --------------------------------------------            :
  1990                              <1> 	;			00H        30.0        10H        7.5                 :
  1991                              <1> 	;			01H        26.7        11H        6.7                 :
  1992                              <1> 	;			02H        24.0        12H        6.0                 :
  1993                              <1> 	;			03H        21.8        13H        5.5                 :
  1994                              <1> 	;			04H        20.0        14H        5.0                 :
  1995                              <1> 	;			05H        18.5        15H        4.6                 :
  1996                              <1> 	;			06H        17.1        16H        4.3                 :
  1997                              <1> 	;			07H        16.0        17H        4.0                 :
  1998                              <1> 	;			08H        15.0        18H        3.7                 :
  1999                              <1> 	;			09H        13.3        19H        3.3                 :
  2000                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2001                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2002                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2003                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2004                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2005                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2006                              <1> 	;									      :
  2007                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2008                              <1> 	;		       							      :
  2009                              <1> 	;                     REGISTER     DELAY                                      :
  2010                              <1> 	;                      VALUE       VALUE                                      :
  2011                              <1> 	;                     ------------------                                      :
  2012                              <1> 	;			00H        250 ms                                     :
  2013                              <1> 	;			01H        500 ms                                     :
  2014                              <1> 	;			02H        750 ms                                     :
  2015                              <1> 	;			03H       1000 ms                                     :
  2016                              <1> 	;-----------------------------------------------------------------------------:
  2017                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2018                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2019                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2020                              <1> 	;		           (CH) = SCAN CODE                                   :
  2021                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2022                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2023                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2024                              <1> 	;-----------------------------------------------------------------------------:		
  2025                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2026                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2027                              <1> 	;-----------------------------------------------------------------------------:
  2028                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2029                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2030                              <1> 	;-----------------------------------------------------------------------------:	
  2031                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2032                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2033                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2034                              <1> 	; OUTPUT					                              :
  2035                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2036                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2037                              <1> 	;------------------------------------------------------------------------------
  2038                              <1> 	
  2039 00000CBE FB                  <1> 	sti				; INTERRUPTS BACK ON
  2040 00000CBF 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2041 00000CC0 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2042                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2043 00000CC1 66BB1000            <1>         mov     bx, KDATA 
  2044 00000CC5 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2045 00000CC7 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2046 00000CC9 742D                <1> 	jz	short _K1		; ASCII_READ
  2047 00000CCB FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2048 00000CCD 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2049 00000CCF FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2050 00000CD1 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2051 00000CD3 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2052 00000CD5 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2053 00000CD7 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2054 00000CDA 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2055                              <1> _KIO1:	
  2056 00000CDC 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2057 00000CDF 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2058 00000CE1 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2059 00000CE3 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2060 00000CE5 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2061 00000CE7 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2062                              <1> _KIO_EXIT:
  2063                              <1> 	;pop	ecx			; RECOVER REGISTER
  2064 00000CE9 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2065 00000CEA 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2066 00000CEB CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2067                              <1> 
  2068                              <1> 	;-----	ASCII CHARACTER
  2069                              <1> _K1E:	
  2070 00000CEC E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2071 00000CF1 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2072 00000CF6 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2073                              <1> _K1:	
  2074 00000CF8 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2075 00000CFD E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2076 00000D02 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2077                              <1> _K1A:
  2078 00000D04 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2079                              <1> 
  2080                              <1> 	;-----	ASCII STATUS
  2081                              <1> _K2E:	
  2082 00000D06 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2083 00000D0B 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2084 00000D0D 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2085 00000D0E E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2086 00000D13 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2087                              <1> _K2:	
  2088 00000D15 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2089 00000D1A 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2090 00000D1C 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2091 00000D1D E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2092 00000D22 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2093 00000D24 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2094 00000D25 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2095 00000D2A EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2096                              <1> _K2A:
  2097 00000D2C 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2098                              <1> _K2B:
  2099                              <1> 	;pop	ecx			; RECOVER REGISTER
  2100 00000D2D 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2101 00000D2E 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2102 00000D2F CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2103                              <1> 
  2104                              <1> ; 24/12/2021
  2105                              <1> ;	;-----	SHIFT STATUS
  2106                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2107                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2108                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2109                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2110                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2111                              <1> ;       shl	ah, 5
  2112                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2113                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2114                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2115                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2116                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2117                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2118                              <1> ;_K3:
  2119                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2120                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2121                              <1> 
  2122                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2123                              <1> _K300:
  2124 00000D32 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2125 00000D34 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2126 00000D36 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2127 00000D39 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2128 00000D3B F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2129 00000D3E 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2130 00000D40 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2131 00000D42 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2132                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2133                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2134 00000D47 C0E705              <1> 	shl	bh, 5
  2135 00000D4A 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2136 00000D4C 08F8                <1> 	or	al, bh			; AND DELAY
  2137 00000D4E E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2138 00000D53 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2139                              <1> 
  2140                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2141                              <1> _K500:
  2142 00000D55 56                  <1> 	push	esi			; SAVE SI (esi)
  2143 00000D56 FA                  <1> 	cli				; 
  2144 00000D57 8B1D[24660000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2145 00000D5D 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2146 00000D5F E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2147 00000D64 3B1D[20660000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2148 00000D6A 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2149 00000D6C 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2150 00000D6F 891D[24660000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2151 00000D75 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2152 00000D77 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2153                              <1> _K502:
  2154 00000D79 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2155                              <1> _K504:
  2156 00000D7B FB                  <1> 	sti				
  2157 00000D7C 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2158 00000D7D E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2159                              <1> 
  2160                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2161                              <1> _K1S:
  2162 00000D82 FA                  <1> 	cli	; 03/12/2014
  2163 00000D83 8B1D[20660000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2164 00000D89 3B1D[24660000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2165                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2166 00000D8F 750F                <1> 	jne	short _k1x ; 03/12/2014
  2167                              <1> 	;
  2168                              <1> 	; 03/12/2014
  2169                              <1> 	; 28/08/2014
  2170                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2171                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2172                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2173                              <1> _K1T:                                   ; ASCII READ
  2174 00000D91 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2175 00000D92 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2176                              <1> _K1U:	
  2177 00000D93 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2178 00000D94 8B1D[20660000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2179 00000D9A 3B1D[24660000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2180                              <1> _k1x:
  2181 00000DA0 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2182 00000DA1 9C                  <1> 	pushf				; SAVE FLAGS
  2183 00000DA2 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2184 00000DA7 8A1D[15660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2185 00000DAD 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2186 00000DAF 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2187 00000DB2 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2188 00000DB4 E86E060000          <1> 	call	SND_LED1
  2189 00000DB9 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2190                              <1> _K1V:
  2191 00000DBA 9D                  <1> 	popf				; RESTORE FLAGS
  2192 00000DBB 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2193 00000DBC 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2194                              <1> 	;
  2195 00000DBE 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2196 00000DC1 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2197 00000DC6 891D[20660000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2198 00000DCC C3                  <1> 	retn				; RETURN
  2199                              <1> 
  2200                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2201                              <1> _K2S:
  2202 00000DCD FA                  <1> 	cli				; INTERRUPTS OFF
  2203 00000DCE 8B1D[20660000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2204 00000DD4 3B1D[24660000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2205 00000DDA 668B03              <1> 	mov	ax, [ebx]
  2206 00000DDD 9C                  <1> 	pushf				; SAVE FLAGS
  2207                              <1> 	;push	ax			; SAVE CODE
  2208                              <1> 	; 24/12/2021
  2209 00000DDE 50                  <1> 	push	eax
  2210 00000DDF E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2211 00000DE4 8A1D[15660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2212 00000DEA 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2213 00000DEC 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2214 00000DEF 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2215 00000DF1 E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2216                              <1> _K2T:
  2217                              <1> 	;pop	ax			; RESTORE CODE
  2218                              <1> 	; 24/12/2021
  2219 00000DF6 58                  <1> 	pop	eax
  2220 00000DF7 9D                  <1> 	popf				; RESTORE FLAGS
  2221 00000DF8 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2222 00000DF9 C3                  <1> 	retn				; RETURN
  2223                              <1> 
  2224                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2225                              <1> _KIO_E_XLAT:
  2226 00000DFA 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2227 00000DFC 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2228 00000DFE 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2229 00000E00 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2230 00000E02 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2231                              <1> _KIO_E_RET:				
  2232 00000E04 C3                  <1> 	retn				; GO BACK
  2233                              <1> 
  2234                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2235                              <1> _KIO_S_XLAT:
  2236 00000E05 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2237 00000E08 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2238 00000E0A 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2239 00000E0C 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2240 00000E0E 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2241 00000E10 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2242 00000E12 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2243                              <1> _kio_ret: ; 03/12/2014
  2244 00000E14 F8                  <1> 	clc
  2245 00000E15 C3                  <1> 	retn
  2246                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2247                              <1> _KIO_S1:				
  2248 00000E16 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2249                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2250 00000E18 C3                  <1> 	retn
  2251                              <1> _KIO_S2:		
  2252 00000E19 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2253 00000E1C 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2254 00000E1E 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2255 00000E20 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2256 00000E22 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2257 00000E24 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2258 00000E26 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2259                              <1> _KIO_S3:
  2260 00000E28 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2261                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2262 00000E2A 75E8                <1> 	jne	short _kio_ret
  2263 00000E2C 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2264 00000E2E 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2265 00000E30 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2266                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2267                              <1> _KIO_USE:
  2268                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2269 00000E32 C3                  <1> 	retn				; RETURN	
  2270                              <1> _KIO_DIS:
  2271 00000E33 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2272 00000E34 C3                  <1> 	retn				; RETURN
  2273                              <1> 
  2274                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2275                              <1> _K4:    
  2276 00000E35 43                  <1> 	inc     ebx
  2277 00000E36 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2278 00000E37 3B1D[1C660000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2279                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2280 00000E3D 7206                <1> 	jb	short _K5
  2281 00000E3F 8B1D[18660000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2282                              <1> _K5:
  2283 00000E45 C3                  <1> 	retn
  2284                              <1> 
  2285                              <1> ; 20/02/2015
  2286                              <1> ; 05/12/2014
  2287                              <1> ; 26/08/2014
  2288                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2289                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2290                              <1> ;
  2291                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2292                              <1> ; rombios source code (06/10/1985)
  2293                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2294                              <1> 
  2295                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2296                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2297                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2298                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2299                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2300                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2301                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2302                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2303                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2304                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2305                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2306                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2307                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2308                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2309                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2310                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2311                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2312                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2313                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2314                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2315                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2316                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2317                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2318                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2319                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2320                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2321                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2322                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2323                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2324                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2325                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2326                              <1> F11_M		equ	87		; F11 KEY MAKE
  2327                              <1> F12_M		equ	88		; F12 KEY MAKE
  2328                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2329                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2330                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2331                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2332                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2333                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2334                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2335                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2336                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2337                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2338                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2339                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2340                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2341                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2342                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2343                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2344                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2345                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2346                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2347                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2348                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2349                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2350                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2351                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2352                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2353                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2354                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2355                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2356                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2357                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2358                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2359                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2360                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2361                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2362                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2363                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2364                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2365                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2366                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2367                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2368                              <1> ;
  2369                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2370                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2371                              <1> INTA00		equ	020h		; 8259 PORT
  2372                              <1> 
  2373                              <1> 
  2374                              <1> kb_int:
  2375                              <1> 
  2376                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2377                              <1> ; 17/10/2015 ('ctrlbrk') 
  2378                              <1> ; 05/12/2014
  2379                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2380                              <1> 	;	      instead of pc-at bios - 1985-)
  2381                              <1> ; 26/08/2014
  2382                              <1> ;
  2383                              <1> ; 03/06/86  KEYBOARD BIOS
  2384                              <1> ;
  2385                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2386                              <1> ;										;
  2387                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2388                              <1> ;										;
  2389                              <1> ;--------------------------------------------------------------------------------
  2390                              <1> 
  2391                              <1> KB_INT_1:
  2392 00000E46 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2393                              <1> 	;push	ebp
  2394 00000E47 50                  <1> 	push	eax
  2395 00000E48 53                  <1> 	push	ebx
  2396 00000E49 51                  <1> 	push	ecx
  2397 00000E4A 52                  <1> 	push	edx
  2398 00000E4B 56                  <1> 	push	esi
  2399 00000E4C 57                  <1> 	push	edi
  2400 00000E4D 1E                  <1> 	push	ds
  2401 00000E4E 06                  <1> 	push	es
  2402 00000E4F FC                  <1> 	cld				; FORWARD DIRECTION
  2403 00000E50 66B81000            <1> 	mov	ax, KDATA
  2404 00000E54 8ED8                <1> 	mov	ds, ax
  2405 00000E56 8EC0                <1> 	mov	es, ax
  2406                              <1> 	;
  2407                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2408 00000E58 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2409 00000E5A E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2410 00000E5F FA                  <1> 	cli				; DISABLE INTERRUPTS
  2411 00000E60 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2412                              <1> KB_INT_01:
  2413 00000E65 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2414 00000E67 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2415 00000E69 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2416                              <1> 	;
  2417                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2418 00000E6B E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2419                              <1> 	;
  2420                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2421                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2422                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2423                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2424                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2425                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2426                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2427                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2428                              <1> 	;
  2429                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2430                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2431 00000E6D FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2432 00000E6E 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2433 00000E70 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2434                              <1> 	;
  2435                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2436 00000E72 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2437 00000E74 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2438                              <1> 	;
  2439                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2440 00000E76 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2441 00000E77 800D[15660000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2442 00000E7E E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2443                              <1> 	;
  2444                              <1> 	;-----	RESEND THE LAST BYTE
  2445                              <1> KB_INT_4:
  2446 00000E83 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2447 00000E84 800D[15660000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2448 00000E8B E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2449                              <1> 	;
  2450                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2451                              <1> KB_INT_2:
  2452                              <1> 	;push 	ax			; SAVE DATA IN
  2453                              <1> 	; 24/12/2021
  2454 00000E90 50                  <1> 	push	eax
  2455 00000E91 E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2456 00000E96 8A1D[15660000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2457 00000E9C 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2458 00000E9E 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2459 00000EA1 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2460 00000EA3 E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2461                              <1> UP0:
  2462                              <1> 	;pop	ax			; RESTORE DATA IN
  2463                              <1> 	; 24/12/2021
  2464 00000EA8 58                  <1> 	pop	eax
  2465                              <1> ;------------------------------------------------------------------------
  2466                              <1> ;	START OF KEY PROCESSING						;
  2467                              <1> ;------------------------------------------------------------------------
  2468 00000EA9 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2469                              <1> 	;
  2470                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2471 00000EAB 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2472                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2473                              <1> 	; 24/12/2021
  2474 00000EAD 7505                <1> 	jne	short K16
  2475 00000EAF E9ED040000          <1> 	jmp	K62
  2476                              <1> K16:	
  2477 00000EB4 8A3D[16660000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2478                              <1> 	;
  2479                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2480 00000EBA F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2481 00000EBD 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2482 00000EBF 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2483 00000EC1 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2484 00000EC3 7507                <1> 	jne	short RST_RD_ID
  2485 00000EC5 800D[16660000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2486                              <1> RST_RD_ID:
  2487 00000ECC 8025[16660000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2488 00000ED3 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2489                              <1> 	; 24/12/2021
  2490                              <1> 	;jmp	K26
  2491                              <1> 	;
  2492                              <1> TST_ID_2:
  2493 00000ED5 8025[16660000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2494 00000EDC 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2495 00000EDE 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2496 00000EE0 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2497 00000EE2 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2498                              <1> 	; 24/12/2021
  2499                              <1> 	;jne	K26
  2500                              <1> 	;
  2501                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2502 00000EE4 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2503 00000EE7 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2504 00000EE9 800D[13660000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2505 00000EF0 E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2506                              <1> KX_BIT:
  2507 00000EF5 800D[16660000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2508 00000EFC E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2509                              <1> 	;
  2510                              <1> NOT_ID:
  2511 00000F01 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2512 00000F03 750E                <1> 	jne	short TEST_E1
  2513 00000F05 800D[16660000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2514 00000F0C EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2515                              <1> 	; 24/12/2021
  2516 00000F0E E9DA010000          <1> 	jmp	K26A	
  2517                              <1> TEST_E1:	
  2518 00000F13 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2519 00000F15 750C                <1> 	jne	short NOT_HC
  2520 00000F17 800D[16660000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2521 00000F1E E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2522                              <1> 	;
  2523                              <1> NOT_HC:
  2524 00000F23 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2525 00000F25 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2526 00000F28 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2527                              <1> 	;
  2528 00000F2A BF[FE640000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2529 00000F2F AE                  <1> 	scasb
  2530                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2531                              <1> 	; 24/12/2021
  2532 00000F30 7458                <1> 	je	short K16B
  2533 00000F32 AE                  <1> 	scasb
  2534 00000F33 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2535 00000F35 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2536                              <1> 	; 24/12/2021
  2537                              <1> 	;jmp	K26
  2538                              <1> 	;
  2539                              <1> NOT_LC_E0:
  2540 00000F37 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2541 00000F3A 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2542 00000F3C B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2543 00000F41 BF[FC640000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2544 00000F46 F2AE                <1> 	repne	scasb			; CHECK IT
  2545 00000F48 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2546                              <1> 	; 24/12/2021
  2547                              <1> 	;je	K26A			
  2548                              <1> 	;
  2549 00000F4A 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2550 00000F4C 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2551                              <1> 	; 24/12/2021
  2552                              <1> 	;jne	K26
  2553 00000F4E F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2554 00000F51 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2555                              <1> 	; 24/12/2021
  2556                              <1> 	;jnz	K26
  2557                              <1>         ; 20/02/2015 
  2558 00000F53 F605[14660000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2559 00000F5A 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2560                              <1> 	; 24/12/2021
  2561                              <1> 	;jnz	K26
  2562 00000F5C E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2563                              <1> 	;
  2564                              <1> 	;-----	TEST FOR SYSTEM KEY
  2565                              <1> T_SYS_KEY:
  2566 00000F61 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2567 00000F63 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2568                              <1> 	;
  2569 00000F65 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2570 00000F68 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2571                              <1> 	;
  2572 00000F6A F605[14660000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2573 00000F71 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2574                              <1> 	;jnz	K26			
  2575                              <1> 	;
  2576 00000F73 800D[14660000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2577 00000F7A B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2578 00000F7C E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2579                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2580 00000F7E B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2581 00000F80 E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2582                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2583                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2584                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2585                              <1> 	;INT	15H			; USER INTERRUPT	
  2586 00000F85 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2587                              <1> 	;
  2588 00000F8A E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2589                              <1> 	;
  2590                              <1> K16C:
  2591 00000F8F 8025[14660000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2592 00000F96 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2593 00000F98 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2594                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2595                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2596                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2597                              <1> 	;
  2598                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2599                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2600                              <1> 	;INT	15H			; USER INTERRUPT
  2601                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2602                              <1> 	;
  2603 00000F9A E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2604                              <1> 	;
  2605                              <1> 	;-----	TEST FOR SHIFT KEYS
  2606                              <1> K16A:
  2607 00000F9F 8A1D[13660000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2608 00000FA5 BF[F8640000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2609 00000FAA B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2610 00000FAF F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2611 00000FB1 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2612                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2613                              <1> 	; 24/12/2021
  2614 00000FB3 7405                <1> 	je	short K17
  2615 00000FB5 E914010000          <1> 	jmp	K25
  2616                              <1> 	;
  2617                              <1> 	;------	SHIFT KEY FOUND
  2618                              <1> K17:
  2619 00000FBA 81EF[F9640000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2620 00000FC0 8AA7[00650000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2621 00000FC6 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2622 00000FC8 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2623                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2624                              <1> 	; 24/12/2021
  2625 00000FCA 7405                <1> 	jz	short K17C
  2626 00000FCC E999000000          <1> 	jmp	K23
  2627                              <1> 	;
  2628                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2629                              <1> K17C:
  2630 00000FD1 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2631 00000FD4 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2632                              <1> 	;
  2633                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2634 00000FD6 0825[13660000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2635 00000FDC A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2636 00000FDE 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2637                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2638                              <1> 	; 24/12/2021
  2639 00000FE0 E901010000          <1> 	jmp	K26
  2640                              <1> K17D:
  2641 00000FE5 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2642 00000FE8 740B                <1> 	jz 	short K17E		; NO, JUMP
  2643 00000FEA 0825[16660000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2644 00000FF0 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2645                              <1> K17E:
  2646 00000FF5 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2647 00000FF7 0825[14660000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2648 00000FFD E9E4000000          <1> 	jmp	K26
  2649                              <1> 	;
  2650                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2651                              <1> K18:					; SHIFT-TOGGLE
  2652 00001002 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2653 00001005 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2654                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2655                              <1> 	; 24/12/2021
  2656 00001007 E9C2000000          <1> 	jmp	K25
  2657                              <1> K18A:
  2658 0000100C 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2659 0000100E 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2660 00001010 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2661 00001013 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2662                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2663                              <1> 	; 24/12/2021
  2664 00001015 E9B4000000          <1> 	jmp	K25
  2665                              <1> K18B:
  2666 0000101A F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2667 0000101D 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2668                              <1> K19:	
  2669 0000101F F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2670 00001022 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2671 00001024 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2672 00001027 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2673                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2674 00001029 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2675 0000102B E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2676                              <1> K21:					; MIGHT BE NUMERIC
  2677 00001030 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2678 00001033 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2679                              <1> 	;
  2680                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2681 00001035 8425[14660000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2682                              <1> 	;jnz	K26
  2683                              <1> 	; 24/12/2021
  2684 0000103B 7405                <1> 	jz	short K22A
  2685 0000103D E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2686                              <1> K22A:
  2687 00001042 0825[14660000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2688 00001048 3025[13660000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2689                              <1> 	;
  2690                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2691 0000104E F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2692 00001051 7407                <1> 	jz	short K22B		; GO IF NOT
  2693                              <1> 	;
  2694                              <1> 	; 24/12/2021
  2695                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2696 00001053 50                  <1> 	push	eax
  2697 00001054 E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2698                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2699 00001059 58                  <1> 	pop	eax
  2700                              <1> K22B:
  2701 0000105A 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2702                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2703                              <1> 	; 24/12/2021
  2704 0000105C 7405                <1> 	je	short K22C
  2705 0000105E E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2706                              <1> K22C:
  2707 00001063 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2708 00001065 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2709                              <1> 	;
  2710                              <1> 	;-----	BREAK SHIFT FOUND
  2711                              <1> K23:					; BREAK-SHIFT-FOUND
  2712 0000106A 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2713 0000106D F6D4                <1> 	not	ah			; INVERT MASK
  2714 0000106F 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2715 00001071 2025[13660000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2716 00001077 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2717 0000107A 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2718                              <1> 	;
  2719 0000107C F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2720 0000107F 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2721 00001081 2025[16660000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2722 00001087 EB08                <1> 	jmp	short K23B		; CONTINUE
  2723                              <1> K23A:
  2724 00001089 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2725 0000108B 2025[14660000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2726                              <1> K23B:
  2727 00001091 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2728 00001093 A0[16660000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2729 00001098 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2730 0000109A 0A05[14660000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2731 000010A0 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2732 000010A2 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2733 000010A4 0805[13660000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2734 000010AA 88E0                <1> 	mov	al, ah
  2735                              <1> K23D:
  2736 000010AC 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2737 000010AE 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2738                              <1> 	;	
  2739                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2740 000010B0 A0[17660000]        <1> 	mov	al, [ALT_INPUT]
  2741 000010B5 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2742 000010B7 8825[17660000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2743 000010BD 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2744 000010BF 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2745 000010C1 E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2746                              <1> 	;
  2747                              <1> K24:					; BREAK-TOGGLE
  2748 000010C6 2025[14660000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2749 000010CC EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2750                              <1> 	;
  2751                              <1> 	;-----	TEST FOR HOLD STATE
  2752                              <1> 					; AL, AH = SCAN CODE
  2753                              <1> K25:					; NO-SHIFT-FOUND
  2754 000010CE 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2755 000010D0 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2756 000010D2 F605[14660000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2757 000010D9 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2758 000010DB 3C45                <1> 	cmp	al, NUM_KEY
  2759 000010DD 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2760 000010DF 8025[14660000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2761                              <1> 	;
  2762                              <1> K26:
  2763 000010E6 8025[16660000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2764                              <1> K26A:					; INTERRUPT-RETURN
  2765 000010ED FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2766 000010EE B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2767 000010F0 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2768                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2769 000010F2 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2770 000010F4 E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2771                              <1> K27A:
  2772 000010F9 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2773 000010FA 07                  <1> 	pop	es			; RESTORE REGISTERS
  2774 000010FB 1F                  <1> 	pop	ds
  2775 000010FC 5F                  <1> 	pop	edi
  2776 000010FD 5E                  <1> 	pop	esi
  2777 000010FE 5A                  <1> 	pop	edx
  2778 000010FF 59                  <1> 	pop	ecx
  2779 00001100 5B                  <1> 	pop	ebx
  2780 00001101 58                  <1> 	pop	eax
  2781                              <1> 	;pop	ebp
  2782 00001102 CF                  <1> 	iret				; RETURN
  2783                              <1> 
  2784                              <1> 	;-----	NOT IN	HOLD STATE
  2785                              <1> K28:					; NO-HOLD-STATE
  2786 00001103 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2787 00001105 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2788                              <1> 	;
  2789 00001107 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2790 0000110A 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2791                              <1>         ; 24/12/2021
  2792                              <1> 	;jz      K38
  2793                              <1> 	;
  2794 0000110C F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2795 0000110F 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2796                              <1> 	; 28/02/2015
  2797 00001111 F605[14660000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2798 00001118 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2799                              <1> 	; 24/12/2021
  2800                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2801                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2802 0000111A E9D1000000          <1> K28A:	jmp	K38
  2803                              <1> 	;
  2804                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2805                              <1> K29:					; TEST-RESET
  2806 0000111F F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2807 00001122 740B                <1> 	jz	short K31		; NO_RESET
  2808 00001124 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2809 00001126 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2810                              <1> 	;
  2811                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2812                              <1>  	; 26/08/2014
  2813                              <1> cpu_reset:
  2814                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2815                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2816 00001128 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2817 0000112A E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2818                              <1> khere:
  2819 0000112C F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2820 0000112D EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2821                              <1> 
  2822                              <1> 	;
  2823                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2824                              <1> K31:					; NO-RESET
  2825 0000112F 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2826 00001131 7507                <1> 	jne	short K311		; NOT THERE
  2827 00001133 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2828 00001135 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2829                              <1> K311:
  2830 0000113A 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2831 0000113C 7509                <1> 	jne	short K312		; NOT THERE
  2832 0000113E 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2833 00001142 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2834                              <1> K312:
  2835 00001147 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2836 00001149 7471                <1>         je	short K37B              ; GO PROCESS
  2837 0000114B 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2838 0000114D 746D                <1>         je	short K37B              ; GO PROCESS
  2839                              <1> 	;
  2840                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2841                              <1> K32:					; ALT-KEY-PAD
  2842 0000114F BF[D4640000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2843 00001154 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2844 00001159 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2845 0000115B 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2846 0000115D F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2847                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2848                              <1> 	; 24/12/2021
  2849 00001160 751C                <1> 	jnz	short K32B
  2850 00001162 81EF[D5640000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2851 00001168 A0[17660000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2852 0000116D B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2853 0000116F F6E4                <1> 	mul	ah
  2854 00001171 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2855 00001174 A2[17660000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2856                              <1> K32A:
  2857 00001179 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2858                              <1> K32B:
  2859                              <1> 	; 24/12/2021
  2860 0000117E EB6A                <1> 	jmp	K37C
  2861                              <1> 	;
  2862                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2863                              <1> K33:					; NO-ALT-KEYPAD
  2864 00001180 C605[17660000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2865 00001187 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2866 0000118C F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2867 0000118E 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2868                              <1> 	;
  2869                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2870                              <1> K34:					; ALT-TOP-ROW
  2871 00001190 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2872 00001192 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2873 00001194 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2874 00001196 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2875 00001198 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2876 0000119B EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2877                              <1> 	;
  2878                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2879                              <1> K35:					; ALT-FUNCTION
  2880 0000119D 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2881 0000119F 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2882 000011A1 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2883 000011A3 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2884 000011A5 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2885 000011A8 EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2886                              <1> K35A:
  2887 000011AA F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2888 000011AD 7425                <1> 	jz	short K37		; NO, JUMP
  2889 000011AF 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2890 000011B1 7510                <1>         jne     short K35B              ; NOT THERE
  2891 000011B3 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2892 000011B7 E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2893                              <1> K37B:
  2894 000011BC B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2895 000011BE E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2896                              <1> K35B:
  2897 000011C3 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2898 000011C5 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2899 000011C7 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2900 000011C9 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2901                              <1>         ; 24/12/2021
  2902                              <1> 	;jne	K26
  2903 000011CB 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2904 000011CF E99C010000          <1> 	jmp	K57			; BUFFER FILL
  2905                              <1> K37:
  2906 000011D4 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2907 000011D6 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2908 000011D8 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2909                              <1>         ;ja	short K32A		; IF SO, IGNORE
  2910 000011DA 0F8706FFFFFF        <1>         ja      K26
  2911 000011E0 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2912                              <1> K37A:
  2913 000011E3 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2914 000011E5 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2915                              <1> K37C:
  2916 000011EA 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2917 000011EC 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2918 000011EE EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2919                              <1> 	;
  2920                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2921                              <1> K38:					; NOT-ALT-SHIFT
  2922                              <1> 					; BL STILL HAS SHIFT FLAGS
  2923 000011F0 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2924 000011F3 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2925                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2926                              <1> 	; 24/12/2021
  2927 000011F5 E9AB000000          <1> 	jmp	K44
  2928                              <1> 	;
  2929                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  2930                              <1> 	;-----	TEST FOR BREAK
  2931                              <1> K38A:
  2932 000011FA 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  2933 000011FC 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  2934 000011FE F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2935 00001201 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  2936 00001203 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  2937 00001206 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  2938                              <1> K38B:
  2939 00001208 8B1D[20660000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  2940 0000120E 891D[24660000]      <1> 	mov	[BUFFER_TAIL], ebx
  2941 00001214 C605[12660000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  2942                              <1> 	;
  2943                              <1> 	;-----	ENABLE KEYBOARD
  2944 0000121B B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  2945 0000121D E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2946                              <1> 	;
  2947                              <1> 	; CTRL+BREAK code here !!!
  2948                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  2949                              <1> 	; 17/10/2015	
  2950 00001222 E830230000          <1> 	call	ctrlbrk ; control+break subroutine
  2951                              <1> 	;
  2952                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  2953                              <1> 	; 24/12/2021
  2954 00001227 29C0                <1> 	sub	eax, eax
  2955 00001229 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  2956                              <1> 	;
  2957                              <1> 	;-----	TEST FOR PAUSE
  2958                              <1> K39:					; NO_BREAK
  2959 0000122E F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2960 00001231 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  2961 00001233 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  2962 00001235 7533                <1> 	jne	short K41		; NO-PAUSE
  2963                              <1> K39P:
  2964 00001237 800D[14660000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  2965                              <1> 	;
  2966                              <1> 	;-----	ENABLE KEYBOARD
  2967 0000123E B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  2968 00001240 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2969                              <1> K39A:
  2970 00001245 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  2971 00001247 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  2972                              <1> 	;
  2973                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  2974 00001249 803D[10660000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  2975 00001250 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  2976 00001252 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  2977 00001256 A0[11660000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  2978 0000125B EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  2979                              <1> 	;
  2980                              <1> K40:					; PAUSE-LOOP
  2981 0000125C F605[14660000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  2982 00001263 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  2983                              <1> 	;
  2984 00001265 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  2985                              <1>         ;
  2986                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  2987                              <1> K41:					; NO-PAUSE
  2988 0000126A 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  2989 0000126C 7513                <1> 	jne	short K42		; NOT-KEY-55
  2990 0000126E F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2991 00001271 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  2992 00001273 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  2993 00001276 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  2994                              <1> K41A:	
  2995 00001278 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  2996 0000127C E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  2997                              <1> 	;
  2998                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  2999                              <1> K42:					; NOT-KEY-55
  3000 00001281 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3001 00001283 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3002 00001285 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3003 00001287 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3004 00001289 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3005 0000128C 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3006 0000128E 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3007 00001292 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3008                              <1> K42A:
  3009                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3010 00001297 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3011                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3012                              <1> 	;;jb	K56 ; 20/02/2015
  3013                              <1> 	;;jmp	K64 ; 20/02/2015
  3014                              <1> K42B:
  3015 00001299 BB[08650000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3016                              <1> 	;;jmp	K64
  3017                              <1> 	;jb	K56 ;; 20/02/2015	
  3018                              <1> 	; 24/12/2021
  3019 0000129E 7267                <1> 	jb	short K45F
  3020 000012A0 E9B9000000          <1> 	jmp	K64	
  3021                              <1>         ;
  3022                              <1> 	;-----	NOT IN CONTROL SHIFT
  3023                              <1> K44:					; NOT-CTL-SHIFT
  3024 000012A5 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3025 000012A7 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3026 000012A9 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3027 000012AC 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3028 000012AE F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3029 000012B1 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3030 000012B3 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3031                              <1> K44A:
  3032 000012B5 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3033 000012B8 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3034                              <1> 	;
  3035                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3036                              <1> K44B:
  3037 000012BA B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3038 000012BC E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3039 000012C1 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3040 000012C3 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3041                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3042                              <1> 	;PUSH 	BP			; SAVE POINTER
  3043                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3044                              <1> 	;POP	BP			; RESTORE POINTER
  3045 000012C5 8025[16660000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3046 000012CC E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3047                              <1> 	;
  3048                              <1> 	;-----	HANDLE IN-CORE KEYS
  3049                              <1> K45:					; NOT-PRINT-SCREEN
  3050 000012D1 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3051 000012D3 7734                <1> 	ja	short K46		; JUMP IF NOT
  3052 000012D5 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3053 000012D7 7505                <1> 	jne	short K45A		; NO, JUMP
  3054 000012D9 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3055 000012DC 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3056                              <1> K45A:
  3057 000012DE B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3058 000012E3 BF[DE640000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3059 000012E8 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3060                              <1> 		; 20/02/2015
  3061 000012EA 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3062                              <1> 	;
  3063 000012EC F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3064 000012EF 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3065                              <1> K45B:
  3066 000012F1 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3067 000012F4 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3068                              <1> 					; NO, LOWERCASE
  3069                              <1> K45C:
  3070 000012F6 BB[60650000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3071 000012FB EB51                <1> 	jmp	short K56	
  3072                              <1> K45D:					; ALMOST-CAPS-STATE
  3073 000012FD F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3074 00001300 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3075                              <1> K45E:
  3076 00001302 BB[B8650000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3077 00001307 EB45                <1> K45F:	jmp	short K56
  3078                              <1> 	;
  3079                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3080                              <1> K46:					; NOT IN-CORE AREA
  3081 00001309 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3082                              <1> 	;ja	short K47		; JUMP IF NOT
  3083                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3084 0000130B 7635                <1> 	jna	short K53		
  3085                              <1> 	;
  3086                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3087                              <1> K47:					; NOT F1 - F10
  3088 0000130D 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3089 0000130F 772D                <1> 	ja	short K52		; JUMP IF NOT
  3090                              <1> 	;
  3091                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3092                              <1> K48:
  3093 00001311 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3094 00001313 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3095 00001315 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3096 00001317 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3097 00001319 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3098 0000131C 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3099                              <1> 	;		
  3100 0000131E F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3101 00001321 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3102 00001323 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3103                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3104 00001326 75DA                <1> 	jnz	short K45E
  3105                              <1> 	;
  3106                              <1> 	;-----	BASE CASE FOR KEYPAD
  3107                              <1> K49:					
  3108 00001328 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3109 0000132A 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3110 0000132C B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3111 0000132E EB40                <1> 	jmp	short K57		; BUFFER FILL
  3112                              <1> K49A:
  3113 00001330 BB[60650000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3114 00001335 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3115                              <1> 	;
  3116                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3117                              <1> K50:					; ALMOST-NUM-STATE
  3118 00001337 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3119 0000133A 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3120 0000133C EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3121                              <1> 	;
  3122                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3123                              <1> K52:					; NOT A NUMPAD KEY
  3124 0000133E 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3125                              <1> 	;jne	short K53		; JUMP IF NOT
  3126                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3127 00001340 74AF                <1> 	je	short K45B		
  3128                              <1> 	;
  3129                              <1> 	;-----	MUST BE F11 OR F12 
  3130                              <1> K53:					; F1 - F10 COME HERE, TOO
  3131 00001342 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3132 00001345 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3133                              <1> 		; 20/02/2015 
  3134 00001347 BB[B8650000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3135 0000134C EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3136                              <1> 	;
  3137                              <1> 	;-----	TRANSLATE THE CHARACTER
  3138                              <1> K56:					; TRANSLATE-CHAR
  3139 0000134E FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3140 00001350 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3141 00001351 F605[16660000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3142 00001358 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3143 0000135A B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3144 0000135C EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3145                              <1> 	;
  3146                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3147                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3148 0000135E FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3149 00001360 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3150 00001361 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3151 00001363 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3152 00001365 F605[16660000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3153 0000136C 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3154 0000136E B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3155                              <1> 	;
  3156                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3157                              <1> K57:					; BUFFER_FILL
  3158 00001370 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3159 00001372 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3160                              <1> 	; 24/12/2021
  3161                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3162 00001374 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3163                              <1> 	; 24/12/2021
  3164 00001377 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3165                              <1> 	;je	K26			; INTERRUPT_RETURN
  3166                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3167 00001379 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3168                              <1> K61:					; NOT-CAPS-STATE
  3169 0000137E 8B1D[24660000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3170 00001384 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3171 00001386 E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3172 0000138B 3B1D[20660000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3173 00001391 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3174 00001393 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3175 00001396 891D[24660000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3176 0000139C E945FDFFFF          <1> 	jmp	K26
  3177                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3178                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3179                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3180                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3181                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3182                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3183                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3184                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3185                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3186                              <1> 	;;jmp   K27                    
  3187                              <1> 	;
  3188                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3189                              <1> K62:
  3190 000013A1 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3191 000013A3 E620                <1> 	out	INTA00, al
  3192 000013A5 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3193 000013A9 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3194 000013AB E89B010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3195 000013B0 E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3196                              <1> 
  3197                              <1> SHIP_IT:
  3198                              <1> 	;---------------------------------------------------------------------------------
  3199                              <1> 	; SHIP_IT
  3200                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3201                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3202                              <1> 	;---------------------------------------------------------------------------------
  3203                              <1> 	;
  3204                              <1> 	;push	ax			; SAVE DATA TO SEND
  3205                              <1> 	; 24/12/2021
  3206 000013B5 50                  <1> 	push	eax
  3207                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3208 000013B6 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3209                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3210 000013B7 B900000100          <1> 	mov	ecx, 10000h			
  3211                              <1> S10:
  3212 000013BC E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3213 000013BE A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3214 000013C0 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3215                              <1> 
  3216                              <1> 	;pop	ax			; GET DATA TO SEND
  3217                              <1> 	; 24/12/2021
  3218 000013C2 58                  <1> 	pop	eax
  3219 000013C3 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3220 000013C5 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3221 000013C6 C3                  <1> 	retn				; RETURN TO CALLER
  3222                              <1> 
  3223                              <1> SND_DATA:
  3224                              <1> 	; ---------------------------------------------------------------------------------
  3225                              <1> 	; SND_DATA
  3226                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3227                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3228                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3229                              <1> 	; ---------------------------------------------------------------------------------
  3230                              <1> 	;
  3231                              <1> 	;push	ax			; SAVE REGISTERS
  3232                              <1> 	;push	bx
  3233                              <1> 	; 24/12/2021
  3234 000013C7 50                  <1> 	push	eax
  3235 000013C8 53                  <1> 	push	ebx
  3236 000013C9 51                  <1> 	push	ecx
  3237 000013CA 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3238 000013CC B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3239                              <1> SD0:
  3240 000013CE FA                  <1> 	cli				; DISABLE INTERRUPTS
  3241 000013CF 8025[15660000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3242                              <1> 	;
  3243                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3244 000013D6 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3245                              <1> SD5:
  3246 000013DB E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3247 000013DD A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3248 000013DF E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3249                              <1> 	;
  3250 000013E1 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3251 000013E3 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3252 000013E5 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3253                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3254 000013E6 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3255                              <1> SD1:
  3256 000013EB F605[15660000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3257 000013F2 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3258 000013F4 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3259                              <1> SD2:
  3260 000013F6 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3261 000013F8 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3262 000013FA 800D[15660000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3263 00001401 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3264                              <1> SD3:
  3265 00001403 F605[15660000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3266 0000140A 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3267                              <1> SD4:	
  3268 0000140C 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3269                              <1> 	;pop	bx
  3270                              <1> 	;pop	ax
  3271                              <1> 	; 24/12/2021
  3272 0000140D 5B                  <1> 	pop	ebx
  3273 0000140E 58                  <1> 	pop	eax
  3274 0000140F C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3275                              <1> 
  3276                              <1> SND_LED:
  3277                              <1> 	; ---------------------------------------------------------------------------------
  3278                              <1> 	; SND_LED
  3279                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3280                              <1> 	;
  3281                              <1> 	;----------------------------------------------------------------------------------
  3282                              <1> 	;
  3283 00001410 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3284 00001411 F605[15660000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3285 00001418 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3286                              <1> 	;
  3287 0000141A 800D[15660000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3288 00001421 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3289 00001423 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3290 00001425 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3291                              <1> SND_LED1:
  3292 00001427 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3293 00001428 F605[15660000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3294 0000142F 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3295                              <1> 	;
  3296 00001431 800D[15660000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3297                              <1> SL0:
  3298 00001438 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3299 0000143A E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3300 0000143F FA                  <1> 	cli
  3301 00001440 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3302 00001445 8025[15660000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3303 0000144C 0805[15660000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3304 00001452 F605[15660000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3305 00001459 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3306                              <1> 	;
  3307 0000145B E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3308 00001460 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3309 00001461 F605[15660000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3310 00001468 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3311                              <1> SL2:
  3312 0000146A B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3313 0000146C E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3314 00001471 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3315                              <1> SL3:
  3316 00001472 8025[15660000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3317                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3318 00001479 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3319 0000147A C3                  <1> 	retn				; RETURN TO CALLER
  3320                              <1> 
  3321                              <1> MAKE_LED:
  3322                              <1> 	;---------------------------------------------------------------------------------
  3323                              <1> 	; MAKE_LED
  3324                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3325                              <1> 	;	THE MODE INDICATORS.
  3326                              <1> 	;---------------------------------------------------------------------------------
  3327                              <1> 	;
  3328                              <1> 	;push 	cx			; SAVE CX
  3329 0000147B A0[13660000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3330 00001480 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3331                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3332                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3333 00001482 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3334 00001485 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3335                              <1> 	;pop	cx
  3336 00001487 C3                  <1> 	retn				; RETURN TO CALLER
  3337                              <1> 
  3338                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3339                              <1> 
  3340                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1775                                  
  1776                                  %include 'video.inc' ; 07/03/2015
  1777                              <1> ; ****************************************************************************
  1778                              <1> ; Retro UNIX 386 v1.1 Kernel - VIDEO.INC
  1779                              <1> ; Last Modification: 24/12/2021
  1780                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1781                              <1> ;
  1782                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1783                              <1> 
  1784                              <1> ; 24/12/2021
  1785                              <1> ; 30/06/2015
  1786                              <1> ; 27/06/2015
  1787                              <1> ; 11/03/2015
  1788                              <1> ; 02/09/2014
  1789                              <1> ; 30/08/2014
  1790                              <1> ; VIDEO FUNCTIONS
  1791                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1792                              <1> 
  1793                              <1> write_tty:
  1794                              <1> 	; 13/08/2015
  1795                              <1> 	; 02/09/2014
  1796                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1797                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1798                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1799                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1800                              <1> 	;
  1801                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1802                              <1> 	;	   AL = Character to be written
  1803                              <1> 	;	   EBX = Video Page (0 to 7)
  1804                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1805                              <1> 
  1806                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1807                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1808                              <1> 
  1809                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1810                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1811                              <1> ;
  1812                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1813                              <1> ;
  1814                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1815                              <1> ;										:
  1816                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1817                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1818                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1819                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1820                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1821                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1822                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1823                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1824                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1825                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1826                              <1> ;   THE 0 COLOR IS USED.							:
  1827                              <1> ;   ENTRY --									:
  1828                              <1> ;     (AH) = CURRENT CRT MODE							:
  1829                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1830                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1831                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1832                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1833                              <1> ;   EXIT -- 									:
  1834                              <1> ;     ALL REGISTERS SAVED							:
  1835                              <1> ;--------------------------------------------------------------------------------
  1836                              <1> 
  1837 00001488 FA                  <1> 	cli
  1838                              <1> 	;
  1839                              <1> 	; READ CURSOR (04/12/2013)
  1840                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1841 00001489 08FF                <1> 	or	bh, bh
  1842 0000148B 0F85AB000000        <1> 	jnz	beeper
  1843                              <1> 	; 01/09/2014
  1844 00001491 803D[10660000]03    <1> 	cmp	byte [CRT_MODE], 3
  1845 00001498 7405                <1> 	je	short m3
  1846                              <1> 	;
  1847 0000149A E876020000          <1> 	call	set_mode
  1848                              <1> m3:
  1849 0000149F 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1850 000014A1 66D1E6              <1> 	shl	si, 1
  1851 000014A4 81C6[466C0000]      <1> 	add	esi, cursor_posn
  1852 000014AA 668B16              <1> 	mov	dx, [esi]
  1853                              <1> 	;
  1854                              <1> 	; dx now has the current cursor position
  1855                              <1> 	;
  1856 000014AD 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1857 000014AF 764D                <1> 	jbe	short u8
  1858                              <1> 	;
  1859                              <1> 	; write the char to the screen
  1860                              <1> u0:	
  1861                              <1> 	; ah = attribute/color
  1862                              <1> 	; al = character
  1863                              <1> 	; bl = video page number (0 to 7)
  1864                              <1> 	; bh = 0
  1865                              <1> 	;
  1866 000014B1 E832020000          <1> 	call	write_c_current
  1867                              <1> 	;
  1868                              <1> 	; position the cursor for next char
  1869 000014B6 FEC2                <1> 	inc	dl		; next column
  1870                              <1> 	;cmp	dl, [CRT_COLS]
  1871 000014B8 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1872 000014BB 0F85E9000000        <1>         jne     set_cpos
  1873 000014C1 B200                <1> 	mov	dl, 0		; column = 0
  1874                              <1> u10:				; (line feed found)
  1875 000014C3 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1876 000014C6 722F                <1> 	jb 	short u6
  1877                              <1> 	;
  1878                              <1> 	; scroll required
  1879                              <1> u1:	
  1880                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1881 000014C8 E8DD000000          <1> 	call	set_cpos
  1882                              <1> 	;
  1883                              <1> 	; determine value to fill with during scroll
  1884                              <1> u2:
  1885                              <1> 	; READ_AC_CURRENT		:
  1886                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1887                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1888                              <1> 	;
  1889                              <1> 	; INPUT				
  1890                              <1> 	;	(AH) = CURRENT CRT MODE
  1891                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1892                              <1> 	;	(DS) = DATA SEGMENT
  1893                              <1> 	;	(ES) = REGEN SEGMENT
  1894                              <1> 	; OUTPUT			
  1895                              <1> 	;	(AL) = CHARACTER READ
  1896                              <1> 	;	(AH) = ATTRIBUTE READ
  1897                              <1> 	;
  1898                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1899                              <1> 	;
  1900                              <1> 	; bl = video page number
  1901                              <1> 	;
  1902 000014CD E834010000          <1> 	call	find_position	; get regen location and port address
  1903                              <1> 	; dx = status port
  1904                              <1> 	; esi = cursor location/address
  1905                              <1> p11:
  1906 000014D2 FB                  <1> 	sti			; enable interrupts
  1907 000014D3 90                  <1> 	nop			; allow for small interupts window
  1908 000014D4 FA                  <1> 	cli			; blocks interrupts for single loop
  1909 000014D5 EC                  <1> 	in	al, dx		; get status from adapter
  1910 000014D6 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1911 000014D8 75F8                <1> 	jnz	short p11	; wait until it is
  1912                              <1> p12:				; now wait for either retrace high
  1913 000014DA EC                  <1> 	in	al, dx		; get status
  1914 000014DB A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1915 000014DD 74FB                <1> 	jz	short p12	; wait until either is active	
  1916                              <1> p13:
  1917 000014DF 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1918 000014E5 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1919                              <1> 	;
  1920                              <1> 	; al = character, ah = attribute
  1921                              <1> 	;
  1922 000014E8 FB                  <1> 	sti
  1923                              <1> 	; bl = video page number 	
  1924                              <1> u3:
  1925                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1926                              <1> 	;;sub	cx, cx		; upper left corner
  1927                              <1> 	;;mov	dh, 25-1 	; lower right row
  1928                              <1> 	;;;mov	dl, [CRT_COLS]
  1929                              <1> 	;mov	dl, 80		; lower right column	
  1930                              <1> 	;;dec	dl
  1931                              <1> 	;;mov	dl, 79
  1932                              <1> 
  1933                              <1> 	;;call	scroll_up	; 04/12/2013
  1934                              <1> 	;;; 11/03/2015
  1935                              <1> 	; 02/09/2014
  1936                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  1937                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  1938                              <1> 	; 11/03/2015
  1939 000014E9 6629C9              <1> 	sub	cx, cx
  1940 000014EC 66BA4F18            <1> 	mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  1941                              <1> 	;
  1942 000014F0 B001                <1> 	mov	al, 1		; scroll 1 line up
  1943                              <1> 		; ah = attribute
  1944 000014F2 E939010000          <1> 	jmp	scroll_up
  1945                              <1> ;u4:
  1946                              <1> 	;;int	10h		; video-call return
  1947                              <1> 				; scroll up the screen
  1948                              <1> 				; tty return
  1949                              <1> ;u5:
  1950                              <1> 	;retn			; return to the caller
  1951                              <1> 
  1952                              <1> u6:				; set-cursor-inc
  1953 000014F7 FEC6                <1> 	inc	dh		; next row
  1954                              <1> 				; set cursor
  1955                              <1> ;u7:					
  1956                              <1> 	;;mov	ah, 02h
  1957                              <1> 	;;jmp	short u4 	; establish the new cursor
  1958                              <1> 	;call	set_cpos
  1959                              <1> 	;jmp 	short u5
  1960 000014F9 E9AC000000          <1> 	jmp     set_cpos
  1961                              <1> 
  1962                              <1> 	; check for control characters
  1963                              <1> u8:
  1964 000014FE 7438                <1> 	je	short u9
  1965 00001500 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  1966 00001502 74BF                <1> 	je	short u10
  1967 00001504 3C07                <1> 	cmp	al, 07h 	; is it a bell
  1968 00001506 7434                <1> 	je	short u11
  1969 00001508 3C08                <1> 	cmp	al, 08h		; is it a backspace
  1970                              <1> 	;jne	short u0
  1971 0000150A 7424                <1> 	je	short bs	; 12/12/2013
  1972                              <1> 	; 12/12/2013 (tab stop)
  1973 0000150C 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  1974 0000150E 75A1                <1> 	jne	short u0
  1975 00001510 88D0                <1> 	mov	al, dl
  1976 00001512 6698                <1> 	cbw
  1977 00001514 B108                <1> 	mov	cl, 8
  1978 00001516 F6F1                <1> 	div	cl
  1979 00001518 28E1                <1> 	sub	cl, ah
  1980                              <1> ts:
  1981                              <1> 	; 02/09/2014
  1982                              <1> 	; 01/09/2014
  1983 0000151A B020                <1> 	mov	al, 20h
  1984                              <1> tsloop:
  1985 0000151C 6651                <1> 	push	cx
  1986 0000151E 6650                <1> 	push	ax
  1987 00001520 30FF                <1> 	xor 	bh, bh
  1988                              <1> 	;mov	bl, [active_page]
  1989 00001522 E878FFFFFF          <1> 	call	m3
  1990 00001527 6658                <1> 	pop	ax  ; ah = attribute/color
  1991 00001529 6659                <1> 	pop	cx
  1992 0000152B FEC9                <1> 	dec	cl
  1993 0000152D 75ED                <1> 	jnz	short tsloop
  1994 0000152F C3                  <1> 	retn
  1995                              <1> bs:	
  1996                              <1> 	; back space found
  1997                              <1> 
  1998 00001530 08D2                <1> 	or	dl, dl 		; is it already at start of line
  1999                              <1> 	;je	short u7 	; set_cursor
  2000 00001532 7476                <1> 	jz	short set_cpos
  2001 00001534 664A                <1> 	dec	dx     		; no -- just move it back
  2002                              <1> 	;jmp	short u7
  2003 00001536 EB72                <1> 	jmp	short set_cpos
  2004                              <1> 
  2005                              <1> 	; carriage return found
  2006                              <1> u9:
  2007 00001538 B200                <1> 	mov	dl, 0 		; move to first column
  2008                              <1> 	;jmp	short u7
  2009 0000153A EB6E                <1> 	jmp	short set_cpos
  2010                              <1> 
  2011                              <1> 	; line feed found
  2012                              <1> ;u10:
  2013                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2014                              <1> ;	jne	short u6 	; no, just set the cursor
  2015                              <1> ;       jmp     u1              ; yes, scroll the screen
  2016                              <1> 
  2017                              <1> beeper: 
  2018                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2019                              <1> 	; 18/01/2014
  2020                              <1> 	; 03/12/2013
  2021                              <1> 	; bell found
  2022                              <1> u11:
  2023 0000153C FB                  <1> 	sti
  2024 0000153D 3A1D[566C0000]      <1> 	cmp	bl, [active_page]
  2025 00001543 7551                <1> 	jne	short u12	; Do not sound the beep 
  2026                              <1> 				; if it is not written on the active page
  2027 00001545 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2028 00001549 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2029                              <1> 	;call	beep		; sound the pod bell
  2030                              <1> 	;jmp	short u5 	; tty_return
  2031                              <1> 	;retn
  2032                              <1> 	
  2033                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2034                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2035                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2036                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2037                              <1> 
  2038                              <1> beep:
  2039                              <1> 	; 07/02/2015
  2040                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2041                              <1> 	; 18/01/2014
  2042                              <1> 	; 03/12/2013
  2043                              <1> 	;
  2044                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2045                              <1> 	;
  2046                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2047                              <1> 	;
  2048                              <1> 	; ENTRY:
  2049                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2050                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2051                              <1> 	; EXIT:				:
  2052                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2053                              <1> 
  2054 0000154B 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2055 0000154C FA                  <1> 	cli			; block interrupts during update
  2056 0000154D B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2057 0000154F E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2058 00001551 EB00                <1> 	jmp	$+2		; I/O delay
  2059 00001553 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2060 00001555 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2061 00001557 EB00                <1> 	jmp	$+2		; I/O delay
  2062 00001559 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2063 0000155B E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2064 0000155D E461                <1> 	in	al, PORT_B	; get current setting of port
  2065 0000155F 88C4                <1> 	mov	ah, al		; save that setting
  2066 00001561 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2067 00001563 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2068                              <1> 	;popf	; 18/01/2014
  2069 00001565 FB                  <1> 	sti
  2070                              <1> g7:				; 1/64 second per count (bl)
  2071 00001566 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2072 0000156B E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2073 00001570 FECB                <1> 	dec	bl		; (bl) length count expired?
  2074 00001572 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2075                              <1> 	;
  2076                              <1> 	;pushf			; save interrupt status
  2077 00001574 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2078 00001575 E461                <1> 	in	al, PORT_B	; get current port value
  2079                              <1>         ;or      al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2080 00001577 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2081 00001579 20C4                <1>         and	ah, al		; someone turned them off during beep
  2082 0000157B 88E0                <1> 	mov	al, ah		; recover value of port
  2083                              <1>         ;or      al, not (GATE2+SPK2) ; force speaker data off
  2084 0000157D 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2085 0000157F E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2086                              <1> 	;popf			; restore interrupt flag state
  2087 00001581 FB                  <1> 	sti
  2088 00001582 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2089 00001587 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2090                              <1> 	;pushf			; save interrupt status
  2091 0000158C FA                  <1> 	cli			; block interrupts during update
  2092 0000158D E461                <1> 	in	al, PORT_B	; get current port value in case	
  2093 0000158F 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2094 00001591 08E0                <1> 	or	al, ah		; recover value of port_b
  2095 00001593 E661                <1> 	out	PORT_B, al	; restore speaker status
  2096 00001595 9D                  <1> 	popf			; restore interrupt flag state
  2097                              <1> u12:	
  2098 00001596 C3                  <1> 	retn
  2099                              <1> 
  2100                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2101                              <1> 
  2102                              <1> WAITF:
  2103                              <1> waitf:
  2104                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2105                              <1> 	; 03/12/2013
  2106                              <1> 	;
  2107                              <1> ;	push ax			; save work register (ah)	
  2108                              <1> ;waitf1:
  2109                              <1> 				; use timer 1 output bits
  2110                              <1> ;	in	al, PORT_B	; read current counter output status
  2111                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2112                              <1> ;	cmp	al, ah		; did it just change
  2113                              <1> ;	je	short waitf1	; wait for a change in output line
  2114                              <1> ;	;
  2115                              <1> ;	mov	ah, al		; save new lflag state
  2116                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2117                              <1> ;	;
  2118                              <1> ;	pop	ax		; restore (ah)
  2119                              <1> ;	retn			; return (cx)=0
  2120                              <1> 
  2121                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2122                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2123                              <1> ; 17/12/2014 (dsectrm2.s)
  2124                              <1> ; WAITF
  2125                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2126                              <1> ;
  2127                              <1> ;---WAITF-----------------------------------------------------------------------
  2128                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2129                              <1> ; ENTRY:
  2130                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2131                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2132                              <1> ; EXIT:
  2133                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2134                              <1> ;	(CX) = 0	
  2135                              <1> ;-------------------------------------------------------------------------------
  2136                              <1> 
  2137                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2138                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2139                              <1> 
  2140                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2141                              <1> 	;PUSH	AX			; SAVE WORK REGISTER (AH)
  2142                              <1> 	; 24/12/2021
  2143 00001597 50                  <1> 	push	eax
  2144                              <1> 	; 16/12/2014
  2145                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2146 00001598 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2147                              <1> ;17/12/2014	
  2148                              <1> ;WAITF1:
  2149                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2150                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2151                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2152                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2153                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2154                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2155                              <1> 	;
  2156                              <1> 	; 17/12/2014
  2157                              <1> 	;
  2158                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2159                              <1> 	;
  2160                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2161                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2162                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2163                              <1> WR_STATE_0:
  2164 0000159A E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2165 0000159C A810                <1> 	TEST	AL,010H
  2166 0000159E 74FA                <1> 	JZ	SHORT WR_STATE_0
  2167                              <1> WR_STATE_1:
  2168 000015A0 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2169 000015A2 A810                <1> 	TEST	AL,010H
  2170 000015A4 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2171 000015A6 E2F2                <1>         LOOP    WR_STATE_0
  2172                              <1> 	;
  2173                              <1> 	;POP	AX			; RESTORE (AH)
  2174                              <1> 	; 24/12/2021
  2175 000015A8 58                  <1> 	pop	eax
  2176 000015A9 C3                  <1> 	RETn				; (CX) = 0
  2177                              <1> 
  2178                              <1> set_cpos:
  2179                              <1> 	; 27/06/2015
  2180                              <1> 	; 01/09/2014
  2181                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2182                              <1> 	;
  2183                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2184                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2185                              <1> 	;
  2186                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2187                              <1> 	;
  2188                              <1> 	; SET_CPOS
  2189                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2190                              <1> 	;	NEW X-Y VALUES PASSED
  2191                              <1> 	; INPUT
  2192                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2193                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2194                              <1> 	; OUTPUT
  2195                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2196                              <1> 	;
  2197 000015AA 0FB6C3              <1>         movzx   eax, bl  ; BL = video page number ; 27/06/2015 (movzx)
  2198 000015AD D0E0                <1>         shl     al, 1   ; word offset
  2199 000015AF BE[466C0000]        <1> 	mov	esi, cursor_posn
  2200 000015B4 01C6                <1>         add     esi, eax
  2201 000015B6 668916              <1> 	mov	[esi], dx ; save the pointer
  2202 000015B9 381D[566C0000]      <1> 	cmp	[active_page], bl
  2203 000015BF 7532                <1> 	jne	short m17
  2204                              <1> 	;call	m18	; CURSOR SET
  2205                              <1> ;m17:			; SET_CPOS_RETURN
  2206                              <1> 	; 01/09/2014
  2207                              <1> ;	retn
  2208                              <1> 		; DX  = row/column
  2209                              <1> m18:
  2210 000015C1 E832000000          <1> 	call	position ; determine location in regen buffer	
  2211 000015C6 668B0D[446C0000]    <1> 	mov	cx, [CRT_START]
  2212 000015CD 6601C1              <1> 	add	cx, ax  ; add char position in regen buffer
  2213                              <1> 			; to the start address (offset) for this page
  2214 000015D0 66D1E9              <1> 	shr	cx, 1	; divide by 2 for char only count
  2215 000015D3 B40E                <1> 	mov	ah, 14	; register number for cursor
  2216                              <1> 	;call	m16	; output value to the 6845	
  2217                              <1> 	;retn
  2218                              <1> 
  2219                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2220                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2221                              <1> m16:
  2222 000015D5 FA                  <1> 	cli
  2223                              <1> 	;mov	dx, [addr_6845] ; address register
  2224 000015D6 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2225 000015DA 88E0                <1> 	mov	al, ah	; get value
  2226 000015DC EE                  <1> 	out	dx, al	; register set
  2227 000015DD 6642                <1> 	inc	dx	; data register
  2228 000015DF EB00                <1> 	jmp	$+2	; i/o delay
  2229 000015E1 88E8                <1> 	mov	al, ch	; data
  2230 000015E3 EE                  <1> 	out	dx, al	
  2231 000015E4 664A                <1> 	dec	dx	
  2232 000015E6 88E0                <1> 	mov	al, ah
  2233 000015E8 FEC0                <1> 	inc	al	; point to other data register
  2234 000015EA EE                  <1> 	out	dx, al	; set for second register
  2235 000015EB 6642                <1> 	inc	dx
  2236 000015ED EB00                <1> 	jmp	$+2	; i/o delay
  2237 000015EF 88C8                <1> 	mov	al, cl	; second data value
  2238 000015F1 EE                  <1> 	out	dx, al
  2239 000015F2 FB                  <1> 	sti
  2240                              <1> m17:
  2241 000015F3 C3                  <1> 	retn
  2242                              <1> 
  2243                              <1> set_ctype:
  2244                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2245                              <1> 	;
  2246                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2247                              <1> 
  2248                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2249                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2250                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2251                              <1> ;          OR NO CURSOR AT ALL
  2252                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2253                              <1> 
  2254                              <1> ;------------------------------------------------
  2255                              <1> ; SET_CTYPE
  2256                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2257                              <1> ; INPUT
  2258                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2259                              <1> ; OUTPUT	
  2260                              <1> ;	NONE
  2261                              <1> ;------------------------------------------------
  2262                              <1> 
  2263 000015F4 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2264                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2265                              <1> 	;call	m16	; output cx register
  2266                              <1> 	;retn
  2267 000015F6 EBDD                <1> 	jmp	m16
  2268                              <1> 
  2269                              <1> 
  2270                              <1> position:
  2271                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2272                              <1> 	; 27/06/2015
  2273                              <1> 	; 02/09/2014
  2274                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2275                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2276                              <1> 	;
  2277                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2278                              <1> 	;
  2279                              <1> 	; POSITION
  2280                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2281                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2282                              <1> 	; INPUT
  2283                              <1> 	;	AX = ROW, COLUMN POSITION
  2284                              <1> 	; OUTPUT
  2285                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2286                              <1> 
  2287                              <1> 		; DX = ROW, COLUMN POSITION
  2288                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2289 000015F8 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2290 000015FA B050                <1> 	mov	al, 80   ; determine bytes to row	
  2291 000015FC F6E6                <1> 	mul	dh 	 ; row value
  2292 000015FE 30F6                <1> 	xor	dh, dh   ; 0	
  2293 00001600 6601D0              <1> 	add	ax, dx	 ; add column value to the result
  2294                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2295                              <1> 	; 24/12/2021
  2296 00001603 D1E0                <1> 	shl	eax, 1
  2297                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2298 00001605 C3                  <1> 	retn
  2299                              <1> 
  2300                              <1> find_position:
  2301                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2302                              <1> 	; 27/06/2015
  2303                              <1> 	; 07/09/2014
  2304                              <1> 	; 02/09/2014
  2305                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2306                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2307 00001606 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2308 00001609 89CE                <1> 	mov	esi, ecx
  2309                              <1> 	;shl	si, 1
  2310 0000160B D1E6                <1> 	shl	esi, 1 ; 24/12/2021
  2311 0000160D 668B96[466C0000]    <1> 	mov	dx, [esi+cursor_posn]
  2312 00001614 7409                <1> 	jz	short p21
  2313                              <1> 	;xor	si, si
  2314 00001616 31F6                <1> 	xor	esi, esi ; 24/12/2021
  2315                              <1> p20:
  2316                              <1> 	;add	si, [CRT_LEN]
  2317 00001618 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2318 0000161D E2F9                <1> 	loop	p20
  2319                              <1> p21:
  2320 0000161F 6621D2              <1> 	and	dx, dx
  2321 00001622 7407                <1> 	jz	short p22
  2322 00001624 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2323 00001629 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2324                              <1> p22:	
  2325                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2326                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2327                              <1> 	;add	dx, 6	; point at status port
  2328 0000162B 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2329                              <1> 	; cx = 0
  2330 0000162F C3                  <1> 	retn
  2331                              <1> 
  2332                              <1> scroll_up:
  2333                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2334                              <1> 	; 16/01/2016
  2335                              <1> 	; 07/09/2014
  2336                              <1> 	; 02/09/2014
  2337                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2338                              <1> 	; 04/04/2014
  2339                              <1> 	; 04/12/2013
  2340                              <1> 	;
  2341                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2342                              <1> 	;
  2343                              <1> 	; SCROLL UP
  2344                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2345                              <1> 	;	ON THE SCREEN
  2346                              <1> 	; INPUT
  2347                              <1> 	;	(AH) = CURRENT CRT MODE
  2348                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2349                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2350                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2351                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2352                              <1> 	;	(DS) = DATA SEGMENT
  2353                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2354                              <1> 	; OUTPUT
  2355                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2356                              <1> 	;
  2357                              <1> 	;	bh = 0  (02/09/2014)
  2358                              <1> 	;
  2359                              <1> 	; ((ah = 3))
  2360                              <1> 	; cl = left upper column
  2361                              <1> 	; ch = left upper row
  2362                              <1> 	; dl = right lower column
  2363                              <1> 	; dh = right lower row
  2364                              <1> 	;
  2365                              <1> 	; al = line count 
  2366                              <1> 	; ah = attribute to be used on blanked line	
  2367                              <1> 	; bl = video page number (0 to 7)
  2368                              <1> 	; 
  2369                              <1> 
  2370                              <1> 	; Test	Line Count
  2371 00001630 08C0                <1> 	or	al, al
  2372 00001632 740C                <1> 	jz	short al_set
  2373 00001634 88F7                <1> 	mov	bh, dh	; subtract lower row from upper row
  2374 00001636 28EF                <1> 	sub	bh, ch
  2375 00001638 FEC7                <1> 	inc	bh	; adjust difference by 1
  2376 0000163A 38C7                <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2377 0000163C 7502                <1> 	jne	short al_set ; if not the we're all set
  2378 0000163E 30C0                <1> 	xor	al, al	; otherwise set al to zero
  2379                              <1> al_set:
  2380 00001640 30FF                <1> 	xor	bh, bh	; 0
  2381                              <1> 	;push	ax
  2382 00001642 50                  <1> 	push	eax ; 24/12/2021
  2383                              <1> 	;mov 	esi, [crt_base]
  2384 00001643 BE00800B00          <1>         mov     esi, 0B8000h  
  2385 00001648 3A1D[566C0000]      <1>         cmp     bl, [active_page]
  2386 0000164E 750B                <1> 	jne	short n0
  2387                              <1> 	;
  2388 00001650 66A1[446C0000]      <1>         mov     ax, [CRT_START]
  2389 00001656 6601C6              <1>         add     si, ax
  2390 00001659 EB0F                <1>         jmp     short n1
  2391                              <1> n0:
  2392 0000165B 20DB                <1>         and     bl, bl
  2393 0000165D 740B                <1> 	jz	short n1
  2394 0000165F 88D8                <1> 	mov	al, bl
  2395                              <1> n0x:
  2396                              <1>         ;add    si, [CRT_LEN]
  2397                              <1>         ;add    esi, 80*25*2 
  2398 00001661 6681C6A00F          <1>         add     si, 80*25*2
  2399 00001666 FEC8                <1>         dec	al
  2400 00001668 75F7                <1> 	jnz	short n0x
  2401                              <1> n1:	
  2402                              <1>         ;Scroll position
  2403                              <1> 	;push	dx
  2404                              <1> 	; 24/12/2021
  2405 0000166A 52                  <1> 	push	edx
  2406 0000166B 6689CA              <1> 	mov	dx, cx	; now, upper left position in DX
  2407 0000166E E885FFFFFF          <1> 	call	position
  2408 00001673 01C6                <1> 	add	esi, eax
  2409 00001675 89F7                <1> 	mov	edi, esi
  2410                              <1> 	;pop	dx	; lower right position in DX
  2411 00001677 5A                  <1> 	pop	edx ; 24/12/2021
  2412 00001678 6629CA              <1> 	sub	dx, cx
  2413 0000167B FEC6                <1> 	inc	dh	; dh = #rows 
  2414 0000167D FEC2                <1> 	inc	dl	; dl = #cols in block
  2415                              <1> 	;pop	ax	; al = line count, ah = attribute
  2416                              <1> 	; 24/12/2021
  2417 0000167F 58                  <1> 	pop	eax	; al = line count, ah = attribute
  2418 00001680 31C9                <1> 	xor	ecx, ecx
  2419 00001682 6689C1              <1> 	mov	cx, ax
  2420                              <1> 	;mov	ah, [CRT_COLS]
  2421 00001685 B450                <1> 	mov	ah, 80
  2422 00001687 F6E4                <1> 	mul	ah	; determine offset to from address
  2423 00001689 6601C0              <1> 	add	ax, ax  ; *2 for attribute byte
  2424                              <1> 	;
  2425                              <1> 	;push	ax	; offset 
  2426                              <1> 	;push	dx
  2427                              <1> 	; 24/12/2021
  2428 0000168C 50                  <1> 	push	eax
  2429 0000168D 52                  <1> 	push	edx
  2430                              <1> 	;
  2431                              <1> 	; 04/04/2014
  2432 0000168E 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2433                              <1> n8:                      ; wait_display_enable
  2434 00001692 EC                  <1>         in      al, dx   ; get port
  2435 00001693 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2436 00001695 74FB                <1> 	jz	short n8 ; wait_display_enable
  2437 00001697 B025                <1> 	mov	al, 25h
  2438 00001699 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2439 0000169B EE                  <1> 	out	dx, al	; turn off video during vertical retrace
  2440                              <1> 	;pop	dx	; #rows, #cols
  2441                              <1>        	;pop	ax	; offset
  2442                              <1> 	; 24/12/2021
  2443 0000169C 5A                  <1> 	pop	edx
  2444 0000169D 58                  <1> 	pop	eax
  2445 0000169E 6691                <1> 	xchg	ax, cx	; 
  2446                              <1> 	; ecx = offset, al = line count, ah = attribute
  2447                              <1> ;n9:
  2448 000016A0 08C0                <1> 	or	al, al
  2449 000016A2 7420                <1>         jz      short n3 
  2450 000016A4 01CE                <1>         add     esi, ecx ; from address for scroll
  2451 000016A6 88F7                <1> 	mov	bh, dh  ; #rows in block
  2452 000016A8 28C7                <1> 	sub	bh, al	; #rows to be moved
  2453                              <1> n2:
  2454                              <1> 	; Move rows
  2455 000016AA 88D1                <1> 	mov	cl, dl	; get # of cols to move
  2456 000016AC 56                  <1> 	push	esi
  2457 000016AD 57                  <1> 	push	edi	; save start address
  2458                              <1> n10:
  2459 000016AE 66A5                <1> 	movsw		; move that line on screen
  2460 000016B0 FEC9                <1> 	dec	cl
  2461 000016B2 75FA                <1>         jnz     short n10
  2462 000016B4 5F                  <1> 	pop	edi
  2463 000016B5 5E                  <1> 	pop	esi	; recover addresses
  2464                              <1>         ;mov    cl, [CRT_COLS] 
  2465                              <1> 	;add	cl, cl
  2466                              <1>         ;mov    ecx, 80*2
  2467 000016B6 66B9A000            <1>         mov     cx, 80*2
  2468 000016BA 01CE                <1>         add     esi, ecx  ; next line
  2469 000016BC 01CF                <1>         add     edi, ecx
  2470 000016BE FECF                <1> 	dec	bh	 ; count of lines to move
  2471 000016C0 75E8                <1> 	jnz	short n2 ; row loop
  2472                              <1> 	; bh = 0
  2473 000016C2 88C6                <1> 	mov	dh, al	 ; #rows	
  2474                              <1> n3:
  2475                              <1> 	; attribute in ah
  2476 000016C4 B020                <1> 	mov	al, ' '	 ; fill with blanks
  2477                              <1> n3x:
  2478                              <1> 	; Clear rows
  2479                              <1>                 ; dh =  #rows
  2480 000016C6 88D1                <1>         mov	cl, dl	; get # of cols to clear
  2481 000016C8 57                  <1>         push    edi     ; save address
  2482                              <1> n11:
  2483 000016C9 66AB                <1>         stosw           ; store fill character
  2484 000016CB FEC9                <1> 	dec	cl
  2485 000016CD 75FA                <1>         jnz     short n11
  2486 000016CF 5F                  <1>         pop     edi     ; recover address
  2487                              <1> 	;mov	cl, [CRT_COLS]
  2488                              <1> 	;add	cl, cl
  2489                              <1>         ;mov    ecx, 80*2
  2490 000016D0 B1A0                <1>         mov	cl, 80*2
  2491 000016D2 01CF                <1>         add     edi, ecx
  2492 000016D4 FECE                <1> 	dec	dh
  2493 000016D6 75EE                <1> 	jnz	short n3x ; 16/01/2016
  2494                              <1> 	;
  2495 000016D8 3A1D[566C0000]      <1> 	cmp	bl, [active_page]
  2496 000016DE 7507                <1> 	jne	short n6
  2497                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2498 000016E0 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2499 000016E2 66BAD803            <1> 	mov	dx, 03D8h ; always set color card port
  2500 000016E6 EE                  <1> 	out	dx, al
  2501                              <1> n6:
  2502 000016E7 C3                  <1> 	retn
  2503                              <1> 
  2504                              <1> 
  2505                              <1> write_c_current:
  2506                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2507                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2508                              <1> 	; 18/01/2014
  2509                              <1> 	; 04/12/2013
  2510                              <1> 	;
  2511                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2512                              <1> 	;
  2513                              <1> 	; WRITE_C_CURRENT
  2514                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2515                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2516                              <1> 	; INPUT	
  2517                              <1> 	;	(AH) = CURRENT CRT MODE
  2518                              <1> 	;	(BH) = DISPLAY PAGE
  2519                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2520                              <1> 	;	(AL) = CHAR TO WRITE
  2521                              <1> 	;	(DS) = DATA SEGMENT
  2522                              <1> 	;	(ES) = REGEN SEGMENT
  2523                              <1> 	; OUTPUT
  2524                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2525                              <1> 
  2526 000016E8 FA                  <1> 	cli		
  2527                              <1> 	; bl = video page
  2528                              <1> 	; al = character
  2529                              <1> 	; ah = color/attribute
  2530                              <1> 	;push	dx
  2531                              <1> 	;push	ax	; save character & attribute/color
  2532                              <1> 	; 24/12/2021
  2533 000016E9 52                  <1> 	push	edx
  2534 000016EA 50                  <1> 	push	eax
  2535 000016EB E816FFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2536                              <1> 	; esi = regen location
  2537                              <1> 	; dx = status port
  2538                              <1> 	;
  2539                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2540                              <1> 	;
  2541                              <1> p41:			; wait for horizontal retrace is low or vertical
  2542 000016F0 FB                  <1> 	sti		; enable interrupts first
  2543 000016F1 3A1D[566C0000]      <1>         cmp     bl, [active_page]
  2544 000016F7 7510                <1> 	jne	short p44 
  2545 000016F9 FA                  <1> 	cli 		; block interrupts for single loop
  2546 000016FA EC                  <1> 	in	al, dx	; get status from the adapter
  2547 000016FB A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2548 000016FD 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2549 000016FF A801                <1> 	test	al, RHRZ ; is horizontal retrace low
  2550 00001701 75ED                <1> 	jnz	short p41 ; wait until it is
  2551                              <1> p42:			;  wait for either retrace high
  2552 00001703 EC                  <1> 	in	al, dx ; get status again
  2553 00001704 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2554 00001706 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2555                              <1> p43:	
  2556 00001708 FB                  <1> 	sti
  2557                              <1> p44:
  2558                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2559                              <1> 	; 24/12/2021
  2560 00001709 58                  <1> 	pop	eax
  2561 0000170A 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2562                              <1> 				; Retro UNIX 386 v1 feature only!
  2563 00001710 668906              <1> 	mov	[esi], ax
  2564                              <1> 	;pop	dx
  2565                              <1> 	; 24/12/2021
  2566 00001713 5A                  <1> 	pop	edx
  2567 00001714 C3                  <1> 	retn
  2568                              <1> 
  2569                              <1> set_mode:
  2570                              <1> 	; 16/01/2016
  2571                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2572                              <1> 	;
  2573                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2574                              <1> 
  2575                              <1> ;------------------------------------------------------
  2576                              <1> ; SET MODE					      :
  2577                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2578                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2579                              <1> ; INPUT						      :
  2580                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2581                              <1> ; OUTPUT					      :
  2582                              <1> ;	NONE					      :
  2583                              <1> ;------------------------------------------------------
  2584                              <1> 
  2585 00001715 57                  <1> 	push	edi ; 16/01/2016
  2586 00001716 53                  <1> 	push	ebx
  2587 00001717 52                  <1> 	push	edx
  2588 00001718 51                  <1> 	push	ecx ; 16/01/2016
  2589 00001719 50                  <1>         push    eax
  2590                              <1> 
  2591                              <1> 	;mov	dx, 03D4h 	; address or color card
  2592 0000171A B003                <1> 	mov	al, 3
  2593                              <1> ;M8:
  2594 0000171C A2[10660000]        <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2595 00001721 B029                <1> 	mov	al, 29h
  2596                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2597 00001723 2437                <1> 	and	al, 037h	; video off, save high resolution bit	
  2598                              <1> 	;push	dx  		; save port value
  2599                              <1> 	;add	dx, 4		; point to control register
  2600 00001725 66BAD803            <1> 	mov	dx, 3D8h
  2601 00001729 EE                  <1> 	out	dx, al		; reset video to off to suppress rolling
  2602                              <1> 	;pop	dx
  2603                              <1> ;M9:
  2604 0000172A BB[48660000]        <1> 	mov	ebx, video_params ; initialization table
  2605                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2606                              <1> 	;xchg 	ah, al
  2607                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2608 0000172F 30E4                <1> 	xor	ah, ah		  ; ah is register number during loop 
  2609                              <1> 	
  2610                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2611 00001731 B910000000          <1> 	mov	ecx, 16 ; 16/01/2016
  2612                              <1> M10:			;  initialization loop
  2613 00001736 88E0                <1> 	mov	al, ah 	; get 6845 register number
  2614 00001738 EE                  <1> 	out	dx, al
  2615 00001739 6642                <1> 	inc	dx      ; point to data port
  2616 0000173B FEC4                <1> 	inc	ah	; next register value
  2617 0000173D 8A03                <1> 	mov	al, [ebx] ; get table value
  2618 0000173F EE                  <1> 	out	dx, al	; out to chip
  2619 00001740 43                  <1> 	inc	ebx	; next in table
  2620 00001741 664A                <1> 	dec	dx	; back to pointer register
  2621 00001743 E2F1                <1> 	loop	M10	; do the whole table
  2622                              <1> 	
  2623                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2624                              <1> 	;xor	ax, ax  
  2625                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2626                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2627                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2628                              <1> 	; black background, light gray characeter color, space character
  2629                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2630                              <1> ;M13:			  ; clear buffer
  2631                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2632                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2633                              <1> 
  2634                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2635                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2636                              <1> 			 ; prepare to output to video enable port
  2637                              <1> 	;add	dx,4	 ; point to the mode control gerister
  2638 00001745 66BAD803            <1> 	mov	dx, 3D8h
  2639                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2640 00001749 B029                <1> 	mov	al, 29h
  2641 0000174B EE                  <1> 	out	dx, al	 ; set video enable port
  2642                              <1> 
  2643                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2644                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2645                              <1> 	;
  2646                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2647                              <1> 	;
  2648                              <1> ;-----	SET CURSOR POSITIONS
  2649                              <1> 	;push	edi
  2650                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2651 0000174C BF[466C0000]        <1> 	mov	edi, cursor_posn
  2652 00001751 B904000000          <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2653 00001756 31C0                <1> 	xor	eax, eax
  2654 00001758 F3AB                <1> 	rep 	stosd	; fill with zeroes
  2655                              <1> 	;pop	edi
  2656                              <1> 
  2657                              <1> ;-----	SET UP OVERSCAN REGISTER
  2658 0000175A 6642                <1> 	inc	dx	; set overscan port to a default
  2659 0000175C B030                <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2660                              <1> ;M14:
  2661 0000175E EE                  <1> 	out	dx, al	; output the correct value to 3D9 port
  2662                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2663                              <1> 
  2664                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2665                              <1> 	;
  2666 0000175F 58                  <1> 	pop	eax
  2667 00001760 59                  <1> 	pop	ecx ; 16/01/2016
  2668 00001761 5A                  <1> 	pop	edx
  2669 00001762 5B                  <1> 	pop	ebx
  2670 00001763 5F                  <1> 	pop	edi ; 16/01/2016
  2671 00001764 C3                  <1> 	retn
  2672                              <1> 	
  2673                              <1> tty_sw:
  2674                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2675                              <1> 	; 30/06/2015
  2676                              <1> 	; 27/06/2015 
  2677                              <1> 	; 07/09/2014
  2678                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2679                              <1> 	;
  2680                              <1> 	; (Modified registers : EAX)
  2681                              <1> 	;
  2682                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2683                              <1> 	;
  2684                              <1> ;act_disp_page:
  2685                              <1> 	; 30/06/2015
  2686                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2687                              <1> 	; 10/12/2013
  2688                              <1> 	; 04/12/2013
  2689                              <1> 	;
  2690                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2691                              <1> 	;
  2692                              <1> 	; ACT_DISP_PAGE
  2693                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2694                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2695                              <1> 	; INPUT
  2696                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2697                              <1> 	; OUTPUT
  2698                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2699                              <1> 
  2700                              <1> 	;cli
  2701                              <1> 
  2702 00001765 53                  <1> 	push	ebx
  2703                              <1> 	;push	cx
  2704                              <1> 	;push	dx
  2705                              <1> 	; 24/12/2021
  2706 00001766 51                  <1> 	push	ecx
  2707 00001767 52                  <1> 	push	edx
  2708                              <1> 	;
  2709 00001768 A2[566C0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2710                              <1> 	;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2711 0000176D 66B9A00F            <1> 	mov	cx, 25*80*2
  2712                              <1> 	; 27/06/2015
  2713 00001771 0FB6D8              <1> 	movzx	ebx, al
  2714                              <1> 	;
  2715 00001774 6698                <1> 	cbw	; 07/09/2014 (ah=0)
  2716 00001776 66F7E1              <1> 	mul 	cx	; display page times regen length
  2717                              <1> 	; 10/12/2013
  2718 00001779 66A3[446C0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2719 0000177F 6689C1              <1> 	mov	cx, ax ; start address to cx
  2720                              <1> 	;sar	cx, 1
  2721 00001782 66D1E9              <1> 	shr	cx, 1	; divide by 2 for 6845 handling
  2722 00001785 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2723 00001787 E849FEFFFF          <1> 	call	m16
  2724                              <1> 	;sal	bx, 1
  2725                              <1> 	; 01/09/2014
  2726 0000178C D0E3                <1> 	shl	bl, 1	; *2 for word offset
  2727 0000178E 81C3[466C0000]      <1> 	add	ebx, cursor_posn
  2728 00001794 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2729 00001797 E825FEFFFF          <1> 	call	m18
  2730                              <1> 	;
  2731                              <1> 	;pop	dx
  2732                              <1> 	;pop	cx
  2733                              <1> 	; 24/12/2021
  2734 0000179C 5A                  <1> 	pop	edx
  2735 0000179D 59                  <1> 	pop	ecx
  2736 0000179E 5B                  <1> 	pop	ebx
  2737                              <1> 	;
  2738                              <1> 	;sti
  2739                              <1> 	;
  2740 0000179F C3                  <1> 	retn
  2741                              <1> 
  2742                              <1> ; % include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2743                              <1> 
  2744                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1777                                  
  1778                                  setup_rtc_int:
  1779                                  ; source: http://wiki.osdev.org/RTC
  1780 000017A0 FA                      	cli		; disable interrupts
  1781                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1782                                  	; in order to change this ...
  1783                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1784                                  	; (rate must be above 2 and not over 15)
  1785                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1786 000017A1 B08A                    	mov	al, 8Ah 
  1787 000017A3 E670                    	out	70h, al ; set index to register A, disable NMI
  1788 000017A5 90                      	nop
  1789 000017A6 E471                    	in	al, 71h ; get initial value of register A
  1790 000017A8 88C4                    	mov 	ah, al
  1791 000017AA 80E4F0                  	and	ah, 0F0h
  1792 000017AD B08A                    	mov	al, 8Ah 
  1793 000017AF E670                    	out	70h, al ; reset index to register A
  1794 000017B1 88E0                    	mov	al, ah
  1795 000017B3 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1796 000017B5 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1797                                  	; enable RTC interrupt
  1798 000017B7 B08B                    	mov	al, 8Bh ;
  1799 000017B9 E670                    	out	70h, al ; select register B and disable NMI
  1800 000017BB 90                      	nop
  1801 000017BC E471                    	in	al, 71h ; read the current value of register B
  1802 000017BE 88C4                    	mov	ah, al  ;
  1803 000017C0 B08B                    	mov 	al, 8Bh ;
  1804 000017C2 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1805 000017C4 88E0                    	mov	al, ah  ;
  1806 000017C6 0C40                    	or	al, 40h ;
  1807 000017C8 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1808 000017CA FB                      	sti
  1809 000017CB C3                      	retn
  1810                                  
  1811                                  ; Write memory information
  1812                                  ; Temporary Code
  1813                                  ; 06/11/2014
  1814                                  ; 14/08/2015 
  1815                                  memory_info:	
  1816 000017CC A1[2C6C0000]            	mov	eax, [memory_size] ; in pages
  1817 000017D1 50                      	push	eax
  1818 000017D2 C1E00C                  	shl	eax, 12		   ; in bytes
  1819 000017D5 BB0A000000              	mov	ebx, 10
  1820 000017DA 89D9                    	mov	ecx, ebx	   ; 10
  1821 000017DC BE[8D680000]            	mov	esi, mem_total_b_str	
  1822 000017E1 E8B2000000              	call	bintdstr
  1823 000017E6 58                      	pop	eax
  1824 000017E7 B107                    	mov	cl, 7
  1825 000017E9 BE[B1680000]            	mov	esi, mem_total_p_str
  1826 000017EE E8A5000000              	call	bintdstr	
  1827                                  	; 14/08/2015
  1828 000017F3 E8BD000000              	call	calc_free_mem
  1829                                  	; edx = calculated free pages
  1830                                  	; ecx = 0
  1831 000017F8 A1[306C0000]            	mov 	eax, [free_pages]
  1832 000017FD 39D0                    	cmp	eax, edx ; calculated free mem value 
  1833                                  		; and initial free mem value are same or not?
  1834 000017FF 751D                    	jne 	short pmim ; print mem info with '?' if not
  1835 00001801 52                      	push 	edx ; free memory in pages	
  1836                                  	;mov 	eax, edx
  1837 00001802 C1E00C                  	shl	eax, 12 ; convert page count
  1838                                  			; to byte count
  1839 00001805 B10A                    	mov	cl, 10
  1840 00001807 BE[D1680000]            	mov	esi, free_mem_b_str
  1841 0000180C E887000000              	call	bintdstr
  1842 00001811 58                      	pop	eax
  1843 00001812 B107                    	mov	cl, 7
  1844 00001814 BE[F5680000]            	mov	esi, free_mem_p_str
  1845 00001819 E87A000000              	call	bintdstr
  1846                                  pmim:
  1847 0000181E BE[7B680000]            	mov	esi, msg_memory_info
  1848                                  pmim_nb:	
  1849 00001823 AC                      	lodsb
  1850 00001824 08C0                    	or	al, al
  1851 00001826 740D                    	jz	short pmim_ok
  1852 00001828 56                      	push	esi
  1853 00001829 31DB                    	xor	ebx, ebx ; 0
  1854                                  			; Video page 0 (bl=0)
  1855 0000182B B407                    	mov	ah, 07h ; Black background, 
  1856                                  			; light gray forecolor
  1857 0000182D E856FCFFFF              	call	write_tty
  1858 00001832 5E                      	pop	esi
  1859 00001833 EBEE                    	jmp	short pmim_nb
  1860                                  pmim_ok:
  1861 00001835 C3                      	retn
  1862                                  
  1863                                  ; Convert binary number to hexadecimal string
  1864                                  ; 10/05/2015  
  1865                                  ; dsectpm.s (28/02/2015)
  1866                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1867                                  ; 01/12/2014
  1868                                  ; 25/11/2014
  1869                                  ;
  1870                                  bytetohex:
  1871                                  	; INPUT ->
  1872                                  	; 	AL = byte (binary number)
  1873                                  	; OUTPUT ->
  1874                                  	;	AX = hexadecimal string
  1875                                  	;
  1876 00001836 53                      	push	ebx
  1877 00001837 31DB                    	xor	ebx, ebx
  1878 00001839 88C3                    	mov	bl, al
  1879 0000183B C0EB04                  	shr	bl, 4
  1880 0000183E 8A9B[88180000]          	mov	bl, [ebx+hexchrs] 	 	
  1881 00001844 86D8                    	xchg	bl, al
  1882 00001846 80E30F                  	and	bl, 0Fh
  1883 00001849 8AA3[88180000]          	mov	ah, [ebx+hexchrs] 
  1884 0000184F 5B                      	pop	ebx	
  1885 00001850 C3                      	retn
  1886                                  
  1887                                  wordtohex:
  1888                                  	; INPUT ->
  1889                                  	; 	AX = word (binary number)
  1890                                  	; OUTPUT ->
  1891                                  	;	EAX = hexadecimal string
  1892                                  	;
  1893 00001851 53                      	push	ebx
  1894 00001852 31DB                    	xor	ebx, ebx
  1895 00001854 86E0                    	xchg	ah, al
  1896 00001856 6650                    	push	ax
  1897 00001858 88E3                    	mov	bl, ah
  1898 0000185A C0EB04                  	shr	bl, 4
  1899 0000185D 8A83[88180000]          	mov	al, [ebx+hexchrs] 	 	
  1900 00001863 88E3                    	mov	bl, ah
  1901 00001865 80E30F                  	and	bl, 0Fh
  1902 00001868 8AA3[88180000]          	mov	ah, [ebx+hexchrs]
  1903 0000186E C1E010                  	shl	eax, 16
  1904 00001871 6658                    	pop	ax
  1905 00001873 5B                      	pop	ebx
  1906 00001874 EBC0                    	jmp	short bytetohex
  1907                                  	;mov	bl, al
  1908                                  	;shr	bl, 4
  1909                                  	;mov	bl, [ebx+hexchrs] 	 	
  1910                                  	;xchg	bl, al	 	
  1911                                  	;and	bl, 0Fh
  1912                                  	;mov	ah, [ebx+hexchrs] 
  1913                                  	;pop	ebx	
  1914                                  	;retn
  1915                                  
  1916                                  dwordtohex:
  1917                                  	; INPUT ->
  1918                                  	; 	EAX = dword (binary number)
  1919                                  	; OUTPUT ->
  1920                                  	;	EDX:EAX = hexadecimal string
  1921                                  	;
  1922 00001876 50                      	push	eax
  1923 00001877 C1E810                  	shr	eax, 16
  1924 0000187A E8D2FFFFFF              	call	wordtohex
  1925 0000187F 89C2                    	mov	edx, eax
  1926 00001881 58                      	pop	eax
  1927 00001882 E8CAFFFFFF              	call	wordtohex
  1928 00001887 C3                      	retn
  1929                                  
  1930                                  ; 10/05/2015
  1931                                  hex_digits:
  1932                                  hexchrs:
  1933 00001888 303132333435363738-     	db '0123456789ABCDEF'
  1933 00001891 39414243444546     
  1934                                  
  1935                                  ; Convert binary number to decimal/numeric string
  1936                                  ; 06/11/2014
  1937                                  ; Temporary Code
  1938                                  ;
  1939                                  
  1940                                  bintdstr:
  1941                                  	; EAX = binary number
  1942                                  	; ESI = decimal/numeric string address
  1943                                  	; EBX = divisor (10)
  1944                                  	; ECX = string length (<=10)
  1945 00001898 01CE                    	add	esi, ecx
  1946                                  btdstr0:
  1947 0000189A 4E                      	dec	esi
  1948 0000189B 31D2                    	xor	edx, edx
  1949 0000189D F7F3                    	div	ebx
  1950 0000189F 80C230                  	add	dl, 30h
  1951 000018A2 8816                    	mov	[esi], dl
  1952 000018A4 FEC9                    	dec	cl
  1953 000018A6 740C                    	jz	btdstr2
  1954 000018A8 09C0                    	or	eax, eax
  1955 000018AA 75EE                    	jnz	short btdstr0
  1956                                  btdstr1:
  1957 000018AC 4E                      	dec	esi
  1958 000018AD C60620                          mov     byte [esi], 20h ; blank space
  1959 000018B0 FEC9                    	dec	cl
  1960 000018B2 75F8                    	jnz	short btdstr1
  1961                                  btdstr2:
  1962 000018B4 C3                      	retn
  1963                                  
  1964                                  ; Calculate free memory pages on M.A.T.
  1965                                  ; 06/11/2014
  1966                                  ; Temporary Code
  1967                                  ;
  1968                                  
  1969                                  calc_free_mem:
  1970 000018B5 31D2                    	xor	edx, edx
  1971                                  	;xor	ecx, ecx
  1972 000018B7 668B0D[406C0000]        	mov	cx, [mat_size] ; in pages
  1973 000018BE C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  1974 000018C1 BE00001000              	mov	esi, MEM_ALLOC_TBL
  1975                                  cfm0:
  1976 000018C6 AD                      	lodsd
  1977 000018C7 51                      	push	ecx
  1978 000018C8 B920000000              	mov	ecx, 32
  1979                                  cfm1:
  1980 000018CD D1E8                    	shr	eax, 1
  1981 000018CF 7301                    	jnc	short cfm2
  1982 000018D1 42                      	inc	edx
  1983                                  cfm2:
  1984 000018D2 E2F9                    	loop	cfm1
  1985 000018D4 59                      	pop	ecx
  1986 000018D5 E2EF                    	loop	cfm0
  1987 000018D7 C3                      	retn
  1988                                  
  1989                                  %include 'diskio.inc'  ; 07/03/2015
  1990                              <1> ; Retro UNIX 386 v1.1 Kernel - DISKIO.INC
  1991                              <1> ; Last Modification: 24/12/2021
  1992                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  1993                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  1994                              <1> 
  1995                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  1996                              <1> 
  1997                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  1998                              <1> 
  1999                              <1> ; 06/02/2015
  2000                              <1> diskette_io:
  2001 000018D8 9C                  <1> 	pushfd
  2002 000018D9 0E                  <1> 	push 	cs
  2003 000018DA E809000000          <1> 	call 	DISKETTE_IO_1
  2004 000018DF C3                  <1> 	retn
  2005                              <1> 	
  2006                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2007                              <1> ;//////////////////////////////////////////////////////
  2008                              <1> 
  2009                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2010                              <1> ; 20/02/2015
  2011                              <1> ; 06/02/2015 (unix386.s)
  2012                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2013                              <1> ;
  2014                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2015                              <1> ;
  2016                              <1> ; ADISK.EQU
  2017                              <1> 
  2018                              <1> ;----- Wait control constants 
  2019                              <1> 
  2020                              <1> ;amount of time to wait while RESET is active.
  2021                              <1> 
  2022                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2023                              <1> 					;at 250 KBS xfer rate.
  2024                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2025                              <1> 
  2026                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2027                              <1> 					;status register to become valid
  2028                              <1> 					;before re-reading.
  2029                              <1> 
  2030                              <1> ;After sending a byte to NEC, status register may remain
  2031                              <1> ;incorrectly set for 24 us.
  2032                              <1> 
  2033                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2034                              <1> 					;RQM low.
  2035                              <1> 
  2036                              <1> ; COMMON.MAC
  2037                              <1> ;
  2038                              <1> ;	Timing macros
  2039                              <1> ;
  2040                              <1> 
  2041                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2042                              <1> 		jmp short $+2
  2043                              <1> %endmacro		
  2044                              <1> 
  2045                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2046                              <1> 		jmp short $+2
  2047                              <1> 		jmp short $+2
  2048                              <1> %endmacro
  2049                              <1> 
  2050                              <1> %macro		NEWIODELAY 0
  2051                              <1> 		out	0EBh,al
  2052                              <1> %endmacro 
  2053                              <1> 
  2054                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2055                              <1> ;;; WAIT_FOR_MEM
  2056                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2057                              <1> ;WAIT_FDU_INT_HI	equ	1
  2058                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2059                              <1> ;;; WAIT_FOR_PORT
  2060                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2061                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2062                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2063                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2064                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2065                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2066                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2067                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2068                              <1> ;;; WAIT_REFRESH
  2069                              <1> ;amount of time to wait for head settle, per unit in parameter
  2070                              <1> ;table = 1 ms.
  2071                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2072                              <1> 
  2073                              <1> 
  2074                              <1> ; //////////////// DISKETTE I/O ////////////////
  2075                              <1> 
  2076                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2077                              <1> 
  2078                              <1> ;----------------------------------------
  2079                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2080                              <1> ;----------------------------------------
  2081                              <1> 
  2082                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2083                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2084                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2085                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2086                              <1> 
  2087                              <1> ;----------------------------------------
  2088                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2089                              <1> ;-------------------------------------------------------------------------------
  2090                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2091                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2092                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2093                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2094                              <1> 
  2095                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2096                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2097                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2098                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2099                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2100                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2101                              <1> 
  2102                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2103                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2104                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2105                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2106                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2107                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2108                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2109                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2110                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2111                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2112                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2113                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2114                              <1> 
  2115                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2116                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2117                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2118                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2119                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2120                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2121                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2122                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2123                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2124                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2125                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2126                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2127                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2128                              <1> 
  2129                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2130                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2131                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2132                              <1> 
  2133                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2134                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2135                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2136                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2137                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2138                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2139                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2140                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2141                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2142                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2143                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2144                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2145                              <1> 
  2146                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2147                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2148                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2149                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2150                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2151                              <1> 
  2152                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2153                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2154                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2155                              <1> INTA01		EQU	021H		; 8259 PORT
  2156                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2157                              <1> INTB01		EQU	0A1H		;
  2158                              <1> 
  2159                              <1> ;-------------------------------------------------------------------------------
  2160                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2161                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2162                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2163                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2164                              <1> ;-------------------------------------------------------------------------------
  2165                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2166                              <1> 
  2167                              <1> ;-------------------------------------------------------------------------------
  2168                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2169                              <1> 
  2170                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2171                              <1> ; (unix386.s <-- dsectrm2.s)
  2172                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2173                              <1> 
  2174                              <1> ; 10/12/2014
  2175                              <1> ;
  2176                              <1> ;int40h:
  2177                              <1> ;	pushf
  2178                              <1> ;	push 	cs
  2179                              <1> ;	;cli
  2180                              <1> ;	call 	DISKETTE_IO_1
  2181                              <1> ;	retn
  2182                              <1> 
  2183                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2184                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2185                              <1> ;
  2186                              <1> 
  2187                              <1> ;-- INT13H ---------------------------------------------------------------------
  2188                              <1> ; DISKETTE I/O
  2189                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2190                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2191                              <1> ; INPUT
  2192                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2193                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2194                              <1> ;		ON ALL DRIVES
  2195                              <1> ;------------------------------------------------------------------------------- 
  2196                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2197                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2198                              <1> ;-------------------------------------------------------------------------------
  2199                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2200                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2201                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2202                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2203                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2204                              <1> ;		320/360	320/360	    0-39
  2205                              <1> ;		320/360	1.2M	    0-39
  2206                              <1> ;		1.2M	1.2M	    0-79
  2207                              <1> ;		720K	720K	    0-79
  2208                              <1> ;		1.44M	1.44M	    0-79	
  2209                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2210                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2211                              <1> ;		320/360	320/360	     1-8/9
  2212                              <1> ;		320/360	1.2M	     1-8/9
  2213                              <1> ;		1.2M	1.2M	     1-15
  2214                              <1> ;		720K	720K	     1-9
  2215                              <1> ;		1.44M	1.44M	     1-18		
  2216                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2217                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2218                              <1> ;		320/360	320/360	        8/9
  2219                              <1> ;		320/360	1.2M	        8/9
  2220                              <1> ;		1.2M	1.2M		15
  2221                              <1> ;		720K	720K		9
  2222                              <1> ;		1.44M	1.44M		18
  2223                              <1> ;
  2224                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2225                              <1> ;
  2226                              <1> ;-------------------------------------------------------------------------------
  2227                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2228                              <1> ;-------------------------------------------------------------------------------
  2229                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2230                              <1> ;-------------------------------------------------------------------------------
  2231                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2232                              <1> ;-------------------------------------------------------------------------------
  2233                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2234                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2235                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2236                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2237                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2238                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2239                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2240                              <1> ;		READ/WRITE ACCESS.
  2241                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2242                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2243                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2244                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2245                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2246                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2247                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2248                              <1> ;
  2249                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2250                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2251                              <1> ;		---------------------------------------------
  2252                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2253                              <1> ;		---------------------------------------------
  2254                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2255                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2256                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2257                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2258                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2259                              <1> ;		---------------------------------------------
  2260                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2261                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2262                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2263                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2264                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2265                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2266                              <1> ;-------------------------------------------------------------------------------
  2267                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2268                              <1> ;	REGISTERS
  2269                              <1> ;	  INPUT
  2270                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2271                              <1> ;	  OUTPUT
  2272                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2273                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2274                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2275                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2276                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2277                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2278                              <1> ;	    (BH) - 0
  2279                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2280                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2281                              <1> ;	    (AX) - 0
  2282                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2283                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2284                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2285                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2286                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2287                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2288                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2289                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2290                              <1> ;-------------------------------------------------------------------------------
  2291                              <1> ;	(AH)= 15H  READ DASD TYPE
  2292                              <1> ;	OUTPUT REGISTERS
  2293                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2294                              <1> ;		00 - DRIVE NOT PRESENT	
  2295                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2296                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2297                              <1> ;		03 - RESERVED (FIXED DISK)
  2298                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2299                              <1> ;-------------------------------------------------------------------------------
  2300                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2301                              <1> ;	OUTPUT REGISTERS
  2302                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2303                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2304                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2305                              <1> ;-------------------------------------------------------------------------------
  2306                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2307                              <1> ;	INPUT REGISTERS
  2308                              <1> ;	(AL) -	00 - NOT USED	
  2309                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2310                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2311                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2312                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2313                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2314                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2315                              <1> ;-------------------------------------------------------------------------------
  2316                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2317                              <1> ;	INPUT REGISTERS
  2318                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2319                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2320                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2321                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2322                              <1> ;	OUTPUT REGISTERS:
  2323                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2324                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2325                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2326                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2327                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2328                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2329                              <1> ;-------------------------------------------------------------------------------
  2330                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2331                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2332                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2333                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2334                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2335                              <1> ;		CHANGE ERROR CODE
  2336                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2337                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2338                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2339                              <1> ;
  2340                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2341                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2342                              <1> ;-------------------------------------------------------------------------------
  2343                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2344                              <1> ;	AH = STATUS OF OPERATION
  2345                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2346                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2347                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2348                              <1> ;		TYPE AH=(15)).
  2349                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2350                              <1> ;	FOR READ/WRITE/VERIFY
  2351                              <1> ;		DS,BX,DX,CX PRESERVED
  2352                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2353                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2354                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2355                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2356                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2357                              <1> ;-------------------------------------------------------------------------------
  2358                              <1> ;
  2359                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2360                              <1> ;
  2361                              <1> ;   -----------------------------------------------------------------
  2362                              <1> ;   |       |       |       |       |       |       |       |       |
  2363                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2364                              <1> ;   |       |       |       |       |       |       |       |       |
  2365                              <1> ;   -----------------------------------------------------------------
  2366                              <1> ;	|	|	|	|	|	|	|	|
  2367                              <1> ;	|	|	|	|	|	-----------------
  2368                              <1> ;	|	|	|	|	|		|
  2369                              <1> ;	|	|	|	|    RESERVED		|
  2370                              <1> ;	|	|	|	|		  PRESENT STATE
  2371                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2372                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2373                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2374                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2375                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2376                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2377                              <1> ;	|	|	|	|	110: RESERVED
  2378                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2379                              <1> ;	|	|	|	|
  2380                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2381                              <1> ;	|	|	|
  2382                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2383                              <1> ;	|	|			DRIVE)
  2384                              <1> ;	|	|
  2385                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2386                              <1> ;
  2387                              <1> ;						00: 500 KBS
  2388                              <1> ;						01: 300 KBS
  2389                              <1> ;						10: 250 KBS
  2390                              <1> ;						11: RESERVED
  2391                              <1> ;
  2392                              <1> ;
  2393                              <1> ;-------------------------------------------------------------------------------
  2394                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2395                              <1> ;-------------------------------------------------------------------------------
  2396                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2397                              <1> ;-------------------------------------------------------------------------------
  2398                              <1> 
  2399                              <1> struc MD
  2400 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2401 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2402 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2403 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2404 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2405 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2406 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2407 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2408 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2409 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2410 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2411 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2412 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2413                              <1> endstruc
  2414                              <1> 
  2415                              <1> BIT7OFF	EQU	7FH
  2416                              <1> BIT7ON	EQU	80H
  2417                              <1> 
  2418                              <1> ;;int13h: ; 16/02/2015
  2419                              <1> ;; 16/02/2015 - 21/02/2015
  2420                              <1> int40h:
  2421 000018E0 9C                  <1> 	pushfd
  2422 000018E1 0E                  <1> 	push 	cs
  2423 000018E2 E801000000          <1> 	call 	DISKETTE_IO_1
  2424 000018E7 C3                  <1> 	retn	
  2425                              <1> 
  2426                              <1> DISKETTE_IO_1:
  2427                              <1> 
  2428 000018E8 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2429 000018E9 55                  <1> 	PUSH	eBP			; USER REGISTER
  2430 000018EA 57                  <1> 	PUSH	eDI			; USER REGISTER
  2431 000018EB 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2432 000018EC 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2433 000018ED 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2434 000018EE 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2435                              <1> 					; [BP]   = SECTOR #
  2436                              <1> 					; [BP+1] = TRACK #
  2437                              <1> 					; [BP+2] = BUFFER OFFSET
  2438                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2439                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2440                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2441                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2442                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2443                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2444                              <1> 					; BH/[BP+3] = 0
  2445                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2446                              <1> 					; DH/[BP+5] = MAX HEAD #
  2447                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2448 000018F0 06                  <1> 	push	es ; 06/02/2015	
  2449 000018F1 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2450 000018F2 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2451                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2452                              <1> 	;mov	cx, cs
  2453                              <1> 	;mov	ds, cx
  2454 000018F3 66B91000            <1> 	mov	cx, KDATA
  2455 000018F7 8ED9                <1>         mov     ds, cx
  2456 000018F9 8EC1                <1>         mov     es, cx
  2457                              <1> 
  2458                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2459 000018FB 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2460 000018FE 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2461 00001900 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2462                              <1> OK_FUNC:
  2463 00001902 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2464 00001905 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2465 00001907 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2466 0000190A 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2467 0000190C 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2468 0000190F 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2469 00001911 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2470                              <1> OK_DRV:
  2471 00001913 31C9                <1> 	xor	ecx, ecx
  2472                              <1> 	;mov	esi, ecx ; 08/02/2015
  2473                              <1> 	; 24/12/2021
  2474 00001915 89CE                <1> 	mov	esi, ecx
  2475 00001917 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2476 00001919 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2477                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2478                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2479 0000191B C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2480 0000191E BB[56190000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2481 00001923 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2482 00001925 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2483 00001927 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2484 00001929 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2485 0000192C 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2486                              <1> 	;
  2487                              <1> 	; 11/12/2014
  2488 0000192F 8815[D1660000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2489                              <1> 	;
  2490 00001935 8A25[AC6C0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2491 0000193B C605[AC6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2492                              <1> 
  2493                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2494                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2495                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2496                              <1> ;
  2497                              <1> ;		DI	: DRIVE #
  2498                              <1> ;		SI-HI	: HEAD #
  2499                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2500                              <1> ;		ES	: BUFFER SEGMENT
  2501                              <1> ;		[BP]	: SECTOR #
  2502                              <1> ;		[BP+1]	: TRACK #
  2503                              <1> ;		[BP+2]	: BUFFER OFFSET
  2504                              <1> ;
  2505                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2506                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2507                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2508                              <1> ;	SPECIFIC ERROR CODE.
  2509                              <1> ;
  2510                              <1> 					; (AH) = @DSKETTE_STATUS
  2511 00001942 FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2512 00001944 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2513 00001945 1F                  <1> 	POP	DS
  2514 00001946 07                  <1> 	pop	es	; 06/02/2015
  2515 00001947 59                  <1> 	POP	eCX
  2516 00001948 5B                  <1> 	POP	eBX
  2517 00001949 5A                  <1> 	POP	eDX
  2518 0000194A 5F                  <1> 	POP	eDI
  2519 0000194B 89E5                <1> 	MOV	eBP, eSP
  2520 0000194D 50                  <1> 	PUSH	eAX
  2521 0000194E 9C                  <1> 	PUSHFd
  2522 0000194F 58                  <1> 	POP	eAX
  2523                              <1> 	;MOV	[BP+6], AX
  2524 00001950 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2525 00001953 58                  <1> 	POP	eAX
  2526 00001954 5D                  <1> 	POP	eBP
  2527 00001955 CF                  <1> 	IRETd
  2528                              <1> 
  2529                              <1> ;-------------------------------------------------------------------------------
  2530                              <1> ; DW --> dd (06/02/2015)
  2531 00001956 [BA190000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2532 0000195A [2F1A0000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2533 0000195E [3F1A0000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2534 00001962 [501A0000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2535 00001966 [611A0000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2536 0000196A [721A0000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2537 0000196E [F61A0000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2538 00001972 [F61A0000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2539 00001976 [021B0000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2540 0000197A [F61A0000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2541 0000197E [F61A0000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2542 00001982 [F61A0000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2543 00001986 [F61A0000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2544 0000198A [F61A0000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2545 0000198E [F61A0000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2546 00001992 [F61A0000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2547 00001996 [F61A0000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2548 0000199A [F61A0000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2549 0000199E [F61A0000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2550 000019A2 [F61A0000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2551 000019A6 [F61A0000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2552 000019AA [C11B0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2553 000019AE [E91B0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2554 000019B2 [221C0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2555 000019B6 [A31C0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2556                              <1> FNC_TAE EQU     $                       ; END
  2557                              <1> 
  2558                              <1> ;-------------------------------------------------------------------------------
  2559                              <1> ; DISK_RESET	(AH = 00H)	
  2560                              <1> ;		RESET THE DISKETTE SYSTEM.
  2561                              <1> ;
  2562                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2563                              <1> ;-------------------------------------------------------------------------------
  2564                              <1> DSK_RESET:
  2565 000019BA 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2566 000019BE FA                  <1> 	CLI				; NO INTERRUPTS
  2567 000019BF A0[AA6C0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2568 000019C4 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2569 000019C6 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2570                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2571 000019C9 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2572 000019CB EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2573 000019CC C605[A96C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2574                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2575                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2576                              <1> 					;      PULSE WIDTH)
  2577                              <1> 	; 19/12/2014
  2578                              <1> 	NEWIODELAY
  2051 000019D3 E6EB                <2>  out 0EBh,al
  2579                              <1> 
  2580                              <1> 	; 17/12/2014 
  2581                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2582 000019D5 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2583                              <1> wdw1:
  2584                              <1> 	NEWIODELAY   ; 27/02/2015
  2051 000019DA E6EB                <2>  out 0EBh,al
  2585 000019DC E2FC                <1> 	loop	wdw1
  2586                              <1> 	;
  2587 000019DE 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2588 000019E0 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2589                              <1> 	; 16/12/2014
  2590                              <1> 	IODELAY
  2046 000019E1 EB00                <2>  jmp short $+2
  2047 000019E3 EB00                <2>  jmp short $+2
  2591                              <1> 	;
  2592                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2593 000019E5 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2594 000019EA 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2595 000019EC 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2596                              <1> NXT_DRV:
  2597                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2598                              <1> 	; 24/12/2021
  2599 000019F0 51                  <1> 	push	ecx
  2600 000019F1 B8[251A0000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2601 000019F6 50                  <1> 	PUSH	eAX			; "
  2602 000019F7 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2603 000019F9 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2604 000019FE 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2605 000019FF E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2606                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2607                              <1> 	; 24/12/2021
  2608 00001A04 59                  <1> 	pop	ecx
  2609 00001A05 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2610 00001A07 3A0D[AD6C0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2611 00001A0D 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2612 00001A0F FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2613 00001A11 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2614 00001A14 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2615                              <1> 	;
  2616 00001A16 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2617                              <1> RESBAC:
  2618 00001A1B E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2619                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2620                              <1> 	; 24/12/2021
  2621 00001A20 89F3                <1> 	mov	ebx, esi
  2622 00001A22 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2623 00001A24 C3                  <1> 	RETn		
  2624                              <1> DR_POP_ERR:
  2625                              <1> 	;POP	CX			; CLEAR STACK
  2626                              <1> 	; 24/12/2021
  2627 00001A25 59                  <1> 	pop	ecx
  2628                              <1> DR_ERR:
  2629 00001A26 800D[AC6C0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2630 00001A2D EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2631                              <1> 
  2632                              <1> ;-------------------------------------------------------------------------------
  2633                              <1> ; DISK_STATUS	(AH = 01H)
  2634                              <1> ;	DISKETTE STATUS.
  2635                              <1> ;
  2636                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2637                              <1> ;
  2638                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2639                              <1> ;-------------------------------------------------------------------------------
  2640                              <1> DSK_STATUS:
  2641 00001A2F 8825[AC6C0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2642 00001A35 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2643                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2644                              <1> 	; 24/12/2021
  2645 00001A3A 89F3                <1> 	mov	ebx, esi
  2646 00001A3C 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2647 00001A3E C3                  <1> 	RETn		
  2648                              <1> 
  2649                              <1> ;-------------------------------------------------------------------------------
  2650                              <1> ; DISK_READ	(AH = 02H)	
  2651                              <1> ;	DISKETTE READ.
  2652                              <1> ;
  2653                              <1> ; ON ENTRY:	DI	: DRIVE #
  2654                              <1> ;		SI-HI	: HEAD #
  2655                              <1> ;		SI-LOW	: # OF SECTORS
  2656                              <1> ;		ES	: BUFFER SEGMENT
  2657                              <1> ;		[BP]	: SECTOR #
  2658                              <1> ;		[BP+1]	: TRACK #
  2659                              <1> ;		[BP+2]	: BUFFER OFFSET
  2660                              <1> ;
  2661                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2662                              <1> ;-------------------------------------------------------------------------------
  2663                              <1> 
  2664                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2665                              <1> 
  2666                              <1> DSK_READ:
  2667 00001A3F 8025[AA6C0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2668 00001A46 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2669 00001A4A E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2670 00001A4F C3                  <1> 	RETn
  2671                              <1> 
  2672                              <1> ;-------------------------------------------------------------------------------
  2673                              <1> ; DISK_WRITE	(AH = 03H)
  2674                              <1> ;	DISKETTE WRITE.
  2675                              <1> ;
  2676                              <1> ; ON ENTRY:	DI	: DRIVE #
  2677                              <1> ;		SI-HI	: HEAD #
  2678                              <1> ;		SI-LOW	: # OF SECTORS
  2679                              <1> ;		ES	: BUFFER SEGMENT
  2680                              <1> ;		[BP]	: SECTOR #
  2681                              <1> ;		[BP+1]	: TRACK #
  2682                              <1> ;		[BP+2]	: BUFFER OFFSET
  2683                              <1> ;
  2684                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2685                              <1> ;-------------------------------------------------------------------------------
  2686                              <1> 
  2687                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2688                              <1> 
  2689                              <1> DSK_WRITE:
  2690 00001A50 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2691 00001A54 800D[AA6C0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2692 00001A5B E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2693 00001A60 C3                  <1> 	RETn
  2694                              <1> 
  2695                              <1> ;-------------------------------------------------------------------------------
  2696                              <1> ; DISK_VERF	(AH = 04H)
  2697                              <1> ;	DISKETTE VERIFY.
  2698                              <1> ;
  2699                              <1> ; ON ENTRY:	DI	: DRIVE #
  2700                              <1> ;		SI-HI	: HEAD #
  2701                              <1> ;		SI-LOW	: # OF SECTORS
  2702                              <1> ;		ES	: BUFFER SEGMENT
  2703                              <1> ;		[BP]	: SECTOR #
  2704                              <1> ;		[BP+1]	: TRACK #
  2705                              <1> ;		[BP+2]	: BUFFER OFFSET
  2706                              <1> ;
  2707                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2708                              <1> ;-------------------------------------------------------------------------------
  2709                              <1> DSK_VERF:
  2710 00001A61 8025[AA6C0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2711 00001A68 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2712 00001A6C E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2713 00001A71 C3                  <1> 	RETn
  2714                              <1> 
  2715                              <1> ;-------------------------------------------------------------------------------
  2716                              <1> ; DISK_FORMAT	(AH = 05H)
  2717                              <1> ;	DISKETTE FORMAT.
  2718                              <1> ;
  2719                              <1> ; ON ENTRY:	DI	: DRIVE #
  2720                              <1> ;		SI-HI	: HEAD #
  2721                              <1> ;		SI-LOW	: # OF SECTORS
  2722                              <1> ;		ES	: BUFFER SEGMENT
  2723                              <1> ;		[BP]	: SECTOR #
  2724                              <1> ;		[BP+1]	: TRACK #
  2725                              <1> ;		[BP+2]	: BUFFER OFFSET
  2726                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2727                              <1> ;
  2728                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2729                              <1> ;-------------------------------------------------------------------------------
  2730                              <1> DSK_FORMAT:
  2731 00001A72 E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2732 00001A77 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2733 00001A7C 800D[AA6C0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2734 00001A83 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2735 00001A88 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2736 00001A8A E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2737 00001A8F E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2738 00001A94 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2739 00001A96 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2740                              <1> FM_WR:
  2741 00001A9B E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2742 00001AA0 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2743 00001AA2 B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2744 00001AA4 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2745 00001AA9 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2746 00001AAB B8[E71A0000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2747 00001AB0 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2748 00001AB1 B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2749 00001AB3 E80E090000          <1> 	CALL	GET_PARM
  2750 00001AB8 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2751 00001ABD B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2752 00001ABF E802090000          <1> 	CALL	GET_PARM
  2753 00001AC4 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2754 00001AC9 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2755 00001ACB E8F6080000          <1> 	CALL	GET_PARM
  2756 00001AD0 E8F7090000          <1> 	CALL	NEC_OUTPUT
  2757 00001AD5 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2758 00001AD7 E8EA080000          <1> 	CALL	GET_PARM
  2759 00001ADC E8EB090000          <1> 	CALL	NEC_OUTPUT
  2760 00001AE1 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2761 00001AE2 E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2762                              <1> FM_DON:
  2763 00001AE7 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2764 00001AEC E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2765                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2766 00001AF1 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2767 00001AF3 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2768 00001AF5 C3                  <1> 	RETn
  2769                              <1> 
  2770                              <1> ;-------------------------------------------------------------------------------
  2771                              <1> ; FNC_ERR
  2772                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2773                              <1> ;	SET BAD COMMAND IN STATUS.
  2774                              <1> ;
  2775                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2776                              <1> ;-------------------------------------------------------------------------------
  2777                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2778                              <1> 	;MOV	AX,SI			; RESTORE AL
  2779                              <1> 	; 24/12/2021
  2780 00001AF6 89F0                <1> 	mov	eax, esi
  2781 00001AF8 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2782 00001AFA 8825[AC6C0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2783 00001B00 F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2784 00001B01 C3                  <1> 	RETn
  2785                              <1> 
  2786                              <1> ;-------------------------------------------------------------------------------
  2787                              <1> ; DISK_PARMS	(AH = 08H)	
  2788                              <1> ;	READ DRIVE PARAMETERS.
  2789                              <1> ;
  2790                              <1> ; ON ENTRY:	DI : DRIVE #
  2791                              <1> ;
  2792                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2793                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2794                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2795                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2796                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2797                              <1> ;		BH/[BP+3] = 0
  2798                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2799                              <1> ;		DH/[BP+5] = MAX HEAD #
  2800                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2801                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2802                              <1> ;		AX        = 0
  2803                              <1> ;
  2804                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2805                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2806                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2807                              <1> ;		       CALLER.
  2808                              <1> ;-------------------------------------------------------------------------------
  2809                              <1> DSK_PARMS:
  2810 00001B02 E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2811                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2812 00001B07 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2813 00001B09 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2814                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2815                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2816                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2817                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2818                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2819                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2820                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2821                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2822                              <1> 	;sub	edx, edx
  2823 00001B0C 66A1[DE660000]      <1> 	mov     ax, [fd0_type]
  2824 00001B12 6621C0              <1> 	and     ax, ax
  2825 00001B15 7473                <1> 	jz      short NON_DRV
  2826 00001B17 FEC2                <1> 	inc     dl
  2827 00001B19 20E4                <1> 	and     ah, ah
  2828 00001B1B 7402                <1> 	jz      short STO_DL
  2829 00001B1D FEC2                <1> 	inc     dl
  2830                              <1> STO_DL:
  2831                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2832 00001B1F 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2833 00001B22 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2834 00001B26 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2835                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2836 00001B28 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2837 00001B2C E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2838                              <1> 	;;20/02/2015
  2839                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2840                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2841 00001B31 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2842 00001B33 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2843 00001B38 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2844                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2845 00001B3A 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2846 00001B3D 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2847 00001B40 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2848 00001B43 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2849                              <1> CHK_EST:
  2850 00001B45 8AA7[B96C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2851 00001B4B F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2852 00001B4E 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2853                              <1> USE_EST:
  2854 00001B50 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2855 00001B53 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2856 00001B56 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2857                              <1> 
  2858                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2859                              <1> 
  2860 00001B58 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2861 00001B5A E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2862 00001B5F 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2863 00001B62 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2864 00001B65 F687[B96C0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2865 00001B6C 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2866                              <1> 
  2867                              <1> ;-----	IT IS 1.44 MB DRIVE
  2868                              <1> 
  2869                              <1> PARM144:
  2870 00001B6E B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2871 00001B70 E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2872 00001B75 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2873 00001B78 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2874                              <1> STO_CX:
  2875 00001B7B 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2876                              <1> ES_DI:
  2877                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2878 00001B7E 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2879                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2880                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2881                              <1> DP_OUT:
  2882 00001B81 E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2883                              <1> 	;XOR	AX,AX			; CLEAR
  2884                              <1> 	; 24/12/2021
  2885 00001B86 31C0                <1> 	xor	eax, eax
  2886 00001B88 F8                  <1> 	CLC
  2887 00001B89 C3                  <1> 	RETn
  2888                              <1> 
  2889                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2890                              <1> 
  2891                              <1> NON_DRV:
  2892                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2893 00001B8A 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2894                              <1> NON_DRV1:
  2895 00001B8D 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2896 00001B92 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2897                              <1> 
  2898                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2899                              <1> 	
  2900 00001B94 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2901                              <1> 	;MOV	AX,SI			; RESTORE AL
  2902 00001B99 89F0                <1> 	mov	eax, esi ; 24/12/2021
  2903 00001B9B B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2904 00001B9D F9                  <1> 	STC
  2905 00001B9E C3                  <1> 	RETn
  2906                              <1> 
  2907                              <1> NON_DRV2:
  2908                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2909 00001B9F 31C0                <1> 	xor	eax, eax	
  2910 00001BA1 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2911                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2912 00001BA5 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  2913                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  2914 00001BA8 89450C              <1> 	mov	[ebp+12], eax
  2915                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2916 00001BAB EBD4                <1> 	JMP	SHORT DP_OUT
  2917                              <1> 
  2918                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  2919                              <1> 
  2920                              <1> USE_EST2:
  2921 00001BAD B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  2922 00001BAF E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2923 00001BB4 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2924 00001BB7 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2925 00001BBA 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  2926 00001BBD 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  2927 00001BBF EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  2928                              <1> 
  2929                              <1> ;-------------------------------------------------------------------------------
  2930                              <1> ; DISK_TYPE (AH = 15H)	
  2931                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  2932                              <1> ;
  2933                              <1> ;  ON ENTRY:	DI = DRIVE #
  2934                              <1> ;
  2935                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  2936                              <1> ;-------------------------------------------------------------------------------
  2937                              <1> DSK_TYPE:
  2938 00001BC1 E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2939 00001BC6 8A87[B96C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  2940 00001BCC 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  2941 00001BCE 7415                <1> 	JZ	short NO_DRV
  2942 00001BD0 B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  2943 00001BD2 A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  2944 00001BD4 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  2945 00001BD6 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  2946                              <1> DT_BACK:
  2947                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  2948 00001BD8 50                  <1> 	push	eax ; 24/12/2021
  2949 00001BD9 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2950                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  2951 00001BDE 58                  <1> 	pop	eax ; 24/12/2021
  2952 00001BDF F8                  <1> 	CLC				; NO ERROR
  2953                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2954                              <1> 	; 24/12/2021
  2955 00001BE0 89F3                <1> 	mov	ebx, esi
  2956 00001BE2 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2957 00001BE4 C3                  <1> 	RETn
  2958                              <1> NO_DRV:	
  2959 00001BE5 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  2960 00001BE7 EBEF                <1> 	JMP	SHORT DT_BACK
  2961                              <1> 
  2962                              <1> ;-------------------------------------------------------------------------------
  2963                              <1> ; DISK_CHANGE	(AH = 16H)
  2964                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  2965                              <1> ;
  2966                              <1> ; ON ENTRY:	DI = DRIVE #
  2967                              <1> ;
  2968                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  2969                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  2970                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  2971                              <1> ;-------------------------------------------------------------------------------
  2972                              <1> DSK_CHANGE:
  2973 00001BE9 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2974 00001BEE 8A87[B96C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  2975 00001BF4 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  2976 00001BF6 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  2977 00001BF8 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  2978 00001BFA 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  2979                              <1> DC0:
  2980 00001BFC E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  2981 00001C01 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  2982                              <1> 
  2983 00001C03 C605[AC6C0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  2984                              <1> 
  2985 00001C0A E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2986 00001C0F E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2987                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2988                              <1> 	; 24/12/2021
  2989 00001C14 89F3                <1> 	mov	ebx, esi
  2990 00001C16 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2991 00001C18 C3                  <1> 	RETn
  2992                              <1> DC_NON:
  2993 00001C19 800D[AC6C0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  2994 00001C20 EBE8                <1> 	JMP	SHORT FINIS
  2995                              <1> 
  2996                              <1> ;-------------------------------------------------------------------------------
  2997                              <1> ; FORMAT_SET	(AH = 17H)
  2998                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  2999                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3000                              <1> ;
  3001                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3002                              <1> ;		DI     = DRIVE #
  3003                              <1> ;
  3004                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3005                              <1> ;		AH = @DSKETTE_STATUS
  3006                              <1> ;		CY = 1 IF ERROR
  3007                              <1> ;-------------------------------------------------------------------------------
  3008                              <1> FORMAT_SET:
  3009 00001C22 E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3010                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3011                              <1> 	; 24/12/2021
  3012 00001C27 56                  <1> 	push	esi
  3013 00001C28 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3014 00001C2B 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3015 00001C2D 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3016 00001C30 80A7[B96C0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3017 00001C37 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3018 00001C39 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3019 00001C3B 808F[B96C0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3020 00001C42 EB48                <1> 	JMP	SHORT S0
  3021                              <1> NOT_320:
  3022 00001C44 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3023 00001C49 803D[AC6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3024 00001C50 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3025                              <1> S3:
  3026 00001C52 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3027 00001C54 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3028 00001C56 808F[B96C0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3029 00001C5D EB2D                <1> 	JMP	SHORT S0
  3030                              <1> NOT_320_12:
  3031 00001C5F 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3032 00001C61 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3033 00001C63 808F[B96C0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3034 00001C6A EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3035                              <1> NOT_12:	
  3036 00001C6C 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3037 00001C6E 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3038                              <1> 
  3039 00001C70 F687[B96C0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3040 00001C77 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3041 00001C79 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3042 00001C7B F687[B96C0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3043 00001C82 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3044                              <1> ASSUME:
  3045 00001C84 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3046                              <1> OR_IT_IN:
  3047 00001C86 0887[B96C0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3048                              <1> S0:
  3049 00001C8C E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3050 00001C91 E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3051                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3052                              <1> 	; 24/12/2021
  3053 00001C96 5B                  <1> 	pop	ebx
  3054 00001C97 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3055 00001C99 C3                  <1> 	RETn
  3056                              <1> FS_ERR:
  3057 00001C9A C605[AC6C0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3058 00001CA1 EBE9                <1> 	JMP	SHORT S0
  3059                              <1> 
  3060                              <1> ;-------------------------------------------------------------------------------
  3061                              <1> ; SET_MEDIA	(AH = 18H)
  3062                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3063                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3064                              <1> ;
  3065                              <1> ; ON ENTRY:
  3066                              <1> ;	[BP]	= SECTOR PER TRACK
  3067                              <1> ;	[BP+1]	= TRACK #
  3068                              <1> ;	DI	= DRIVE #
  3069                              <1> ;
  3070                              <1> ; ON EXIT:
  3071                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3072                              <1> ;	IF NO ERROR:
  3073                              <1> ;		AH = 0
  3074                              <1> ;		CY = 0
  3075                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3076                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3077                              <1> ;	IF ERROR:	
  3078                              <1> ;		AH = @DSKETTE_STATUS
  3079                              <1> ;		CY = 1
  3080                              <1> ;-------------------------------------------------------------------------------
  3081                              <1> SET_MEDIA:
  3082 00001CA3 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3083 00001CA8 F687[B96C0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3084 00001CAF 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3085 00001CB1 E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3086 00001CB6 803D[AC6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3087 00001CBD 746B                <1> 	JE	short SM_RTN
  3088 00001CBF C605[AC6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3089                              <1> SM_CMOS:
  3090 00001CC6 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3091                              <1> 	;;20/02/2015
  3092                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3093                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3094 00001CCB 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3095 00001CCD E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3096 00001CD2 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3097 00001CD4 57                  <1> 	PUSH	eDI			; SAVE REG.
  3098 00001CD5 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3099 00001CD7 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3100                              <1> DR_SEARCH:
  3101 00001CDC 8AA3[5C660000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3102 00001CE2 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3103 00001CE5 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3104 00001CE7 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3105                              <1> DR_FND:
  3106 00001CE9 8BBB[5D660000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3107                              <1> MD_SEARCH:
  3108 00001CEF 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3109 00001CF2 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3110 00001CF5 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3111 00001CF7 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3112 00001CFA 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3113 00001CFD 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3114                              <1> NXT_MD:
  3115                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3116 00001CFF 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3117 00001D02 E2D8                <1> 	LOOP    DR_SEARCH
  3118 00001D04 5F                  <1> 	POP	eDI			; RESTORE REG.
  3119                              <1> MD_NOT_FND:
  3120 00001D05 C605[AC6C0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3121 00001D0C EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3122                              <1> MD_FND:
  3123 00001D0E 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3124 00001D11 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3125 00001D13 7502                <1> 	JNE	short MD_SET
  3126 00001D15 0C20                <1> 	OR	AL,DBL_STEP
  3127                              <1> MD_SET:
  3128                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3129 00001D17 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3130 00001D1A 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3131 00001D1C 5F                  <1> 	POP	eDI
  3132 00001D1D 80A7[B96C0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3133 00001D24 0887[B96C0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3134                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3135                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3136                              <1> SM_RTN:
  3137 00001D2A E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3138 00001D2F E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3139 00001D34 C3                  <1> 	RETn
  3140                              <1> 
  3141                              <1> ;----------------------------------------------------------------
  3142                              <1> ; DR_TYPE_CHECK							:
  3143                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3144                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3145                              <1> ; ON ENTRY:							:
  3146                              <1> ;	AL = DRIVE TYPE						:
  3147                              <1> ; ON EXIT:							:
  3148                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3149                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3150                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3151                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3152                              <1> ; REGISTERS ALTERED: eBX						:
  3153                              <1> ;----------------------------------------------------------------		
  3154                              <1> DR_TYPE_CHECK:
  3155                              <1> 	;PUSH	AX			
  3156                              <1> 	; 24/12/2021
  3157 00001D35 50                  <1> 	push	eax
  3158 00001D36 51                  <1> 	PUSH	eCX
  3159 00001D37 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3160 00001D39 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3161                              <1> TYPE_CHK:	
  3162 00001D3E 8AA3[5C660000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3163 00001D44 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3164 00001D46 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3165                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3166 00001D48 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3167 00001D4B E2F1                <1> 	LOOP    TYPE_CHK
  3168                              <1> 	;
  3169 00001D4D BB[BB660000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3170                              <1> 					; Default for GET_PARM (11/12/2014)
  3171                              <1> 	;
  3172 00001D52 F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3173 00001D53 EB06                <1> 	JMP	SHORT TYPE_RTN
  3174                              <1> DR_TYPE_VALID:
  3175 00001D55 8B9B[5D660000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3176                              <1> TYPE_RTN:
  3177 00001D5B 59                  <1> 	POP	eCX
  3178                              <1> 	;POP	AX
  3179                              <1> 	; 24/12/2021
  3180 00001D5C 58                  <1> 	pop	eax
  3181 00001D5D C3                  <1> 	RETn	
  3182                              <1> 		
  3183                              <1> ;----------------------------------------------------------------
  3184                              <1> ; SEND_SPEC							:
  3185                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3186                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3187                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3188                              <1> ; ON EXIT:	NONE						:	
  3189                              <1> ; REGISTERS ALTERED: CX, DX					:
  3190                              <1> ;----------------------------------------------------------------		
  3191                              <1> SEND_SPEC:
  3192 00001D5E 50                  <1> 	PUSH	eAX			; SAVE AX
  3193 00001D5F B8[851D0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3194 00001D64 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3195 00001D65 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3196 00001D67 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3197 00001D6C 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3198 00001D6E E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3199 00001D73 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3200 00001D78 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3201 00001D7A E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3202 00001D7F E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3203 00001D84 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3204                              <1> SPECBAC:
  3205 00001D85 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3206 00001D86 C3                  <1> 	RETn
  3207                              <1> 
  3208                              <1> ;----------------------------------------------------------------
  3209                              <1> ; SEND_SPEC_MD							:
  3210                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3211                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3212                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3213                              <1> ; ON EXIT:	NONE						:	
  3214                              <1> ; REGISTERS ALTERED: AX						:
  3215                              <1> ;----------------------------------------------------------------		
  3216                              <1> SEND_SPEC_MD:
  3217 00001D87 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3218 00001D88 B8[A51D0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3219 00001D8D 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3220 00001D8E B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3221 00001D90 E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3222 00001D95 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3223 00001D97 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3224 00001D9C 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3225 00001D9F E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3226 00001DA4 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3227                              <1> SPEC_ESBAC:
  3228 00001DA5 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3229 00001DA6 C3                  <1> 	RETn
  3230                              <1> 
  3231                              <1> ;-------------------------------------------------------------------------------
  3232                              <1> ; XLAT_NEW  
  3233                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3234                              <1> ;	MODE TO NEW ARCHITECTURE.
  3235                              <1> ;
  3236                              <1> ; ON ENTRY:	DI = DRIVE #
  3237                              <1> ;-------------------------------------------------------------------------------
  3238                              <1> XLAT_NEW:
  3239 00001DA7 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3240 00001DAA 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3241 00001DAC 80BF[B96C0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3242 00001DB3 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3243 00001DB5 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3244 00001DB8 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3245 00001DBB A0[B86C0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3246 00001DC0 D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3247 00001DC2 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3248 00001DC4 80A7[B96C0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3249 00001DCB 0887[B96C0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3250                              <1> XN_OUT:
  3251 00001DD1 C3                  <1> 	RETn
  3252                              <1> DO_DET:
  3253 00001DD2 E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3254 00001DD7 C3                  <1> 	RETn
  3255                              <1> 
  3256                              <1> ;-------------------------------------------------------------------------------
  3257                              <1> ; XLAT_OLD 
  3258                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3259                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3260                              <1> ;
  3261                              <1> ; ON ENTRY:	DI = DRIVE
  3262                              <1> ;-------------------------------------------------------------------------------
  3263                              <1> XLAT_OLD:
  3264 00001DD8 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3265                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3266                              <1>         ;ja	XO_OUT
  3267                              <1>         ; 24/12/2021
  3268 00001DDB 77F4                <1> 	ja	short XN_OUT
  3269 00001DDD 80BF[B96C0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3270 00001DE4 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3271                              <1> 
  3272                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3273                              <1> 
  3274 00001DE6 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3275 00001DE9 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3276 00001DEC B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3277 00001DEE D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3278 00001DF0 8425[B86C0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3279 00001DF6 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3280                              <1> 
  3281                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3282                              <1> 
  3283 00001DF8 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3284 00001DFA D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3285 00001DFC F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3286 00001DFE 2025[B86C0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3287                              <1> 
  3288                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3289                              <1> 
  3290 00001E04 8A87[B96C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3291 00001E0A 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3292 00001E0C D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3293 00001E0E 0805[B86C0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3294                              <1> 
  3295                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3296                              <1> 
  3297                              <1> SAVE_SET:
  3298 00001E14 8AA7[B96C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3299 00001E1A 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3300 00001E1C 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3301 00001E1F 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3302 00001E22 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3303 00001E24 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3304 00001E26 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3305 00001E29 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3306 00001E2B F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3307 00001E2E 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3308                              <1> UNKNO:
  3309 00001E30 B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3310 00001E32 EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3311                              <1> CHK_144:
  3312 00001E34 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3313                              <1> 	;;20/02/2015
  3314                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3315 00001E39 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3316 00001E3B 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3317 00001E3D 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3318 00001E3F B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3319 00001E41 EB0C                <1> 	JMP	SHORT TST_DET
  3320                              <1> CHK_250:
  3321 00001E43 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3322 00001E45 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3323 00001E48 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3324 00001E4A F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3325 00001E4D 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3326                              <1> TST_DET:
  3327 00001E4F F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3328 00001E52 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3329 00001E54 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3330                              <1> AL_SET:
  3331 00001E56 80A7[B96C0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3332 00001E5D 0887[B96C0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3333                              <1> XO_OUT:
  3334 00001E63 C3                  <1> 	RETn
  3335                              <1> 
  3336                              <1> ;-------------------------------------------------------------------------------
  3337                              <1> ; RD_WR_VF
  3338                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3339                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3340                              <1> ;
  3341                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3342                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3343                              <1> ;
  3344                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3345                              <1> ;-------------------------------------------------------------------------------
  3346                              <1> RD_WR_VF:
  3347                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3348 00001E64 50                  <1> 	push	eax ; 24/12/2021
  3349 00001E65 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3350 00001E6A E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3351                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3352 00001E6F 58                  <1> 	pop	eax ; 24/12/2021
  3353                              <1> DO_AGAIN:
  3354                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3355 00001E70 50                  <1> 	push	eax ; 24/12/2021
  3356 00001E71 E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3357                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3358 00001E76 58                  <1> 	pop	eax ; 24/12/2021
  3359                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3360                              <1> 	; 24/12/2021
  3361 00001E77 7305                <1> 	jnc	short RWV
  3362 00001E79 E9C3000000          <1> 	jmp	RWV_END
  3363                              <1> RWV:
  3364                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3365 00001E7E 50                  <1> 	push	eax ; 24/12/2021
  3366 00001E7F 8AB7[B96C0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3367 00001E85 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3368 00001E88 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3369                              <1> 	;;20/02/2015
  3370                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3371 00001E8D 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3372 00001E8F 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3373 00001E91 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3374 00001E93 F687[B96C0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3375 00001E9A 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3376 00001E9C B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3377 00001E9E EB0F                <1> 	JMP	SHORT RWV_2
  3378                              <1> RWV_1:
  3379 00001EA0 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3380 00001EA2 F687[B96C0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3381 00001EA9 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3382 00001EAB B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3383 00001EAD EB04                <1> 	jmp	short rwv_3
  3384                              <1> RWV_2:
  3385 00001EAF 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3386 00001EB1 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3387                              <1> rwv_3:
  3388 00001EB3 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3389 00001EB8 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3390                              <1> 
  3391                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3392                              <1> 
  3393 00001EBA 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3394 00001EBB 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3395 00001EBD B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3396                              <1> RWV_DR_SEARCH:
  3397 00001EC2 8AA3[5C660000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3398 00001EC8 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3399 00001ECB 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3400 00001ECD 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3401                              <1> RWV_DR_FND:
  3402 00001ECF 8BBB[5D660000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3403                              <1> RWV_MD_SEARH:
  3404 00001ED5 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3405 00001ED8 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3406                              <1> RWV_NXT_MD:
  3407                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3408 00001EDA 83C305              <1> 	add	eBX, 5
  3409 00001EDD E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3410 00001EDF 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3411                              <1> 
  3412                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3413                              <1> 
  3414                              <1> RWV_ASSUME:
  3415 00001EE0 BB[7A660000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3416 00001EE5 F687[B96C0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3417 00001EEC 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3418 00001EEE BB[94660000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3419 00001EF3 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3420                              <1> 
  3421                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3422                              <1> 	 			
  3423                              <1> RWV_MD_FND:
  3424 00001EF5 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3425 00001EF7 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3426                              <1> 	
  3427                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3428                              <1> 
  3429                              <1> RWV_MD_FND1:
  3430 00001EF8 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3431 00001EFD E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3432 00001F02 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3433 00001F04 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3434                              <1> RWV_DBL:
  3435 00001F09 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3436 00001F0A E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3437 00001F0F 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3438 00001F10 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3439                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3440 00001F12 58                  <1> 	pop	eax ; 24/12/2021
  3441                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3442 00001F13 50                  <1> 	push	eax ; 24/12/2021
  3443 00001F14 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3444 00001F15 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3445 00001F1A 5B                  <1> 	POP	eBX 
  3446                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3447 00001F1B 58                  <1> 	pop	eax ; 24/12/2021
  3448 00001F1C 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3449                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3450 00001F1E 50                  <1> 	push	eax ; 24/12/2021
  3451 00001F1F 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3452 00001F20 E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3453 00001F25 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3454 00001F26 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3455 00001F28 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3456 00001F2D 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3457 00001F2F E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3458                              <1> CHK_RET:
  3459 00001F34 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3460                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3461 00001F39 58                  <1> 	pop	eax ; 24/12/2021
  3462 00001F3A 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3463 00001F3C E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3464                              <1> RWV_END:
  3465 00001F41 E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3466 00001F46 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3467                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3468                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3469 00001F4B 50                  <1> 	push	eax ; 24/12/2021
  3470 00001F4C E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3471                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3472 00001F51 58                  <1> 	pop	eax ; 24/12/2021
  3473 00001F52 E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3474 00001F57 C3                  <1> 	RETn
  3475                              <1> 
  3476                              <1> ;-------------------------------------------------------------------------------
  3477                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3478                              <1> ;-------------------------------------------------------------------------------
  3479                              <1> SETUP_STATE:
  3480 00001F58 F687[B96C0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3481 00001F5F 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3482 00001F61 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3483 00001F65 F687[B96C0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3484 00001F6C 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3485 00001F6E F687[B96C0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3486 00001F75 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3487 00001F77 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3488                              <1> AX_SET:	
  3489 00001F7B 80A7[B96C0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3490 00001F82 08A7[B96C0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3491 00001F88 8025[B46C0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3492 00001F8F C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3493 00001F92 0805[B46C0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3494                              <1> J1C:	
  3495 00001F98 C3                  <1> 	RETn
  3496                              <1> 
  3497                              <1> ;-------------------------------------------------------------------------------
  3498                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3499                              <1> ;-------------------------------------------------------------------------------
  3500                              <1> FMT_INIT:
  3501 00001F99 F687[B96C0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3502 00001FA0 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3503 00001FA2 E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3504                              <1> 	;; 20/02/2015
  3505                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3506 00001FA7 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3507 00001FA9 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3508                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3509 00001FAB 8AA7[B96C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3510 00001FB1 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3511 00001FB4 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3512 00001FB6 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3513 00001FB8 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3514 00001FBB EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3515                              <1> N_360:	
  3516 00001FBD FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3517 00001FBF 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3518                              <1> F1_RATE:
  3519 00001FC1 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3520 00001FC4 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3521                              <1> N_12:	
  3522 00001FC6 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3523 00001FC8 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3524 00001FCA F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3525 00001FCD 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3526 00001FCF F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3527 00001FD2 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3528 00001FD4 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3529 00001FD7 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3530                              <1> N_720:
  3531 00001FD9 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3532 00001FDB 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3533 00001FDD EBE2                <1> 	JMP	SHORT F1_RATE
  3534                              <1> ISNT_12: 
  3535 00001FDF 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3536                              <1> 
  3537                              <1> SKP_STATE:
  3538 00001FE2 88A7[B96C0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3539                              <1> F1_OUT:
  3540 00001FE8 C3                  <1> 	RETn
  3541                              <1> CL_DRV:	
  3542 00001FE9 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3543 00001FEB EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3544                              <1> 
  3545                              <1> ;-------------------------------------------------------------------------------
  3546                              <1> ; MED_CHANGE	
  3547                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3548                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3549                              <1> ;
  3550                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3551                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3552                              <1> ;-------------------------------------------------------------------------------
  3553                              <1> MED_CHANGE:
  3554 00001FED E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3555 00001FF2 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3556 00001FF4 80A7[B96C0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3557                              <1> 
  3558                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3559                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3560                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3561                              <1> 
  3562 00001FFB 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3563 00001FFE B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3564 00002000 D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3565 00002002 F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3566 00002004 FA                  <1> 	CLI				; NO INTERRUPTS
  3567 00002005 2005[AA6C0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3568 0000200B FB                  <1> 	STI				; INTERRUPTS ENABLED
  3569 0000200C E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3570                              <1> 
  3571                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3572                              <1> 
  3573 00002011 E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3574 00002016 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3575 00002018 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3576 0000201D 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3577 0000201F E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3578 00002024 C605[AC6C0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3579                              <1> OK1:
  3580 0000202B E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3581 00002030 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3582                              <1> OK4:
  3583 00002032 C605[AC6C0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3584                              <1> OK2:		
  3585 00002039 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3586 0000203A C3                  <1> 	RETn
  3587                              <1> MC_OUT:
  3588 0000203B F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3589 0000203C C3                  <1> 	RETn
  3590                              <1> 
  3591                              <1> ;-------------------------------------------------------------------------------
  3592                              <1> ; SEND_RATE
  3593                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3594                              <1> ; ON ENTRY:	DI = DRIVE #
  3595                              <1> ; ON EXIT:	NONE
  3596                              <1> ; REGISTERS ALTERED: DX
  3597                              <1> ;-------------------------------------------------------------------------------
  3598                              <1> SEND_RATE:
  3599                              <1> 	;PUSH	AX			; SAVE REG.
  3600                              <1> 	; 24/12/2021
  3601 0000203D 50                  <1> 	push	eax
  3602 0000203E 8025[B46C0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3603 00002045 8A87[B96C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3604 0000204B 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3605 0000204D 0805[B46C0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3606 00002053 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3607 00002056 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3608 0000205A EE                  <1> 	OUT	DX,AL
  3609                              <1> 	;POP	AX			; RESTORE REG.
  3610                              <1> 	; 24/12/2021
  3611 0000205B 58                  <1> 	pop	eax
  3612 0000205C C3                  <1> 	RETn
  3613                              <1> 
  3614                              <1> ;-------------------------------------------------------------------------------
  3615                              <1> ; CHK_LASTRATE
  3616                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3617                              <1> ; ON ENTRY:
  3618                              <1> ;	DI = DRIVE #
  3619                              <1> ; ON EXIT:
  3620                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3621                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3622                              <1> ; REGISTERS ALTERED: DX
  3623                              <1> ;-------------------------------------------------------------------------------
  3624                              <1> CHK_LASTRATE:
  3625                              <1> 	;PUSH	AX			; SAVE REG.
  3626                              <1> 	; 24/12/2021
  3627 0000205D 50                  <1> 	push	eax
  3628 0000205E 2225[B46C0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3629 00002064 8A87[B96C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3630 0000206A 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3631 0000206E 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3632                              <1> 					; ZF = 1 RATE IS THE SAME
  3633                              <1> 	;POP	AX			; RESTORE REG.
  3634                              <1> 	; 24/12/2021
  3635 00002070 58                  <1> 	pop	eax
  3636 00002071 C3                  <1> 	RETn
  3637                              <1> 
  3638                              <1> ;-------------------------------------------------------------------------------
  3639                              <1> ; DMA_SETUP
  3640                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3641                              <1> ;
  3642                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3643                              <1> ;
  3644                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3645                              <1> ;-------------------------------------------------------------------------------
  3646                              <1> 
  3647                              <1> ; SI = Head #, # of Sectors or DASD Type
  3648                              <1> 
  3649                              <1> ; 22/08/2015
  3650                              <1> ; 08/02/2015 - Protected Mode Modification
  3651                              <1> ; 06/02/2015 - 07/02/2015
  3652                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3653                              <1> ; (DMA Addres = Physical Address)
  3654                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3655                              <1> ;
  3656                              <1> ; 04/02/2016 (clc)
  3657                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3658                              <1> ; 16/12/2014 (IODELAY)
  3659                              <1> 
  3660                              <1> DMA_SETUP:
  3661                              <1> 
  3662                              <1> ;; 20/02/2015
  3663 00002072 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3664 00002075 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3665 0000207B 7569                <1> 	jnz	short dma_bnd_err_stc
  3666                              <1> 	;
  3667                              <1> 	;push	ax			; DMA command
  3668                              <1> 	; 24/12/2021
  3669 0000207D 50                  <1> 	push	eax
  3670 0000207E 52                  <1> 	push	edx			; *
  3671 0000207F B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3672 00002081 E840030000          <1> 	call	GET_PARM		; 
  3673 00002086 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3674                              <1> 	;mov	ax, si			; Sector count
  3675                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3676                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3677                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3678                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3679                              <1> 	; 24/12/2021
  3680 00002088 89F2                <1> 	mov	edx, esi
  3681 0000208A 29C0                <1> 	sub	eax, eax
  3682 0000208C 88D4                <1> 	mov	ah, dl
  3683 0000208E D1E8                <1> 	shr	eax, 1
  3684 00002090 D3E0                <1> 	shl	eax, cl
  3685                              <1> 	;
  3686 00002092 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3687 00002094 6689C1              <1> 	mov	cx, ax
  3688 00002097 5A                  <1> 	pop	edx			; *
  3689                              <1> 	;pop	ax
  3690                              <1> 	; 24/12/2021
  3691 00002098 58                  <1> 	pop	eax
  3692 00002099 3C42                <1> 	cmp	al, 42h
  3693 0000209B 7507                <1>         jne     short NOT_VERF
  3694 0000209D BA0000FF00          <1> 	mov	edx, 0FF0000h
  3695 000020A2 EB08                <1> 	jmp	short J33
  3696                              <1> NOT_VERF:
  3697 000020A4 6601CA              <1> 	add	dx, cx			; check for overflow
  3698 000020A7 723E                <1> 	jc	short dma_bnd_err
  3699                              <1> 	;
  3700 000020A9 6629CA              <1> 	sub	dx, cx			; Restore start address
  3701                              <1> J33:
  3702 000020AC FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3703 000020AD E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3704                              <1> 	IODELAY				; WAIT FOR I/O
  2046 000020AF EB00                <2>  jmp short $+2
  2047 000020B1 EB00                <2>  jmp short $+2
  3705 000020B3 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3706 000020B5 89D0                <1> 	mov	eax,edx			; Buffer address
  3707 000020B7 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3708                              <1> 	IODELAY				; WAIT FOR I/O
  2046 000020B9 EB00                <2>  jmp short $+2
  2047 000020BB EB00                <2>  jmp short $+2
  3709 000020BD 88E0                <1> 	MOV	AL,AH
  3710 000020BF E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3711 000020C1 C1E810              <1> 	shr	eax,16
  3712                              <1> 	IODELAY				; I/O WAIT STATE
  2046 000020C4 EB00                <2>  jmp short $+2
  2047 000020C6 EB00                <2>  jmp short $+2
  3713 000020C8 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3714                              <1> 	IODELAY
  2046 000020CA EB00                <2>  jmp short $+2
  2047 000020CC EB00                <2>  jmp short $+2
  3715 000020CE 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3716 000020D1 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3717                              <1> 	IODELAY				; WAIT FOR I/O
  2046 000020D3 EB00                <2>  jmp short $+2
  2047 000020D5 EB00                <2>  jmp short $+2
  3718 000020D7 88E0                <1> 	MOV	AL,AH
  3719 000020D9 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3720                              <1> 	IODELAY
  2046 000020DB EB00                <2>  jmp short $+2
  2047 000020DD EB00                <2>  jmp short $+2
  3721 000020DF FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3722 000020E0 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3723 000020E2 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3724                              <1> 
  3725 000020E4 F8                  <1> 	clc	; 04/02/2016
  3726 000020E5 C3                  <1> 	retn
  3727                              <1> 
  3728                              <1> dma_bnd_err_stc:
  3729 000020E6 F9                  <1> 	stc
  3730                              <1> dma_bnd_err:
  3731 000020E7 C605[AC6C0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3732 000020EE C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3733                              <1> 
  3734                              <1> ;; 16/12/2014
  3735                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3736                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3737                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3738                              <1> ;;	IODELAY
  3739                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3740                              <1> ;;	;SIODELAY
  3741                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3742                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3743                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3744                              <1> ;;      ;JMP	SHORT J33
  3745                              <1> ;;;NOT_VERF:	
  3746                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3747                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3748                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3749                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3750                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3751                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3752                              <1> ;;	;JNC	short J33
  3753                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3754                              <1> ;;;J33:
  3755                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3756                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3757                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3758                              <1> ;;	IODELAY
  3759                              <1> ;;	MOV	AL,AH
  3760                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3761                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3762                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3763                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3764                              <1> ;;	IODELAY
  3765                              <1> ;;	;AND	AL,00001111B
  3766                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3767                              <1> ;;	;SIODELAY
  3768                              <1> ;;
  3769                              <1> ;;;----- DETERMINE COUNT
  3770                              <1> ;;	sub	eax, eax ; 08/02/2015
  3771                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3772                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3773                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3774                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3775                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3776                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3777                              <1> ;;	CALL	GET_PARM		; "
  3778                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3779                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3780                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3781                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3782                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3783                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3784                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3785                              <1> ;;	IODELAY
  3786                              <1> ;;	MOV	AL, AH
  3787                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3788                              <1> ;;	;IODELAY
  3789                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3790                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3791                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3792                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3793                              <1> ;;	add	ecx, eax ; 08/02/2015
  3794                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3795                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3796                              <1> ;;	SIODELAY
  3797                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3798                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3799                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3800                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3801                              <1> ;;	jz	short NO_BAD
  3802                              <1> ;;dma_bnd_err:
  3803                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3804                              <1> ;;NO_BAD:
  3805                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3806                              <1> 
  3807                              <1> ;-------------------------------------------------------------------------------
  3808                              <1> ; FMTDMA_SET
  3809                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3810                              <1> ;
  3811                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3812                              <1> ;
  3813                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3814                              <1> ;-------------------------------------------------------------------------------
  3815                              <1> 
  3816                              <1> 	; 24/12/2021
  3817                              <1> FMTDMA_SET:
  3818                              <1> ;; 20/02/2015 modification	
  3819 000020EF 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3820 000020F2 F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3821 000020F8 75EC                <1> 	jnz	short dma_bnd_err_stc
  3822                              <1> 	;
  3823                              <1> 	;push	dx			; *
  3824                              <1> 	; 24/12/2021
  3825 000020FA 52                  <1> 	push	edx
  3826 000020FB B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3827 000020FD E8C4020000          <1> 	call	GET_PARM		; "
  3828                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3829                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3830                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3831                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3832                              <1> 	;mov	cx, ax
  3833                              <1> 	; 24/12/2021
  3834 00002102 29C9                <1> 	sub	ecx, ecx
  3835 00002104 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3836 00002106 D1E1                <1> 	shl	ecx, 1
  3837 00002108 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3838 0000210A 6649                <1> 	dec	cx
  3839                              <1> 	;pop	dx			; *
  3840                              <1> 	; 24/12/2021
  3841 0000210C 5A                  <1> 	pop	edx
  3842 0000210D 6601CA              <1> 	add	dx, cx			; check for overflow
  3843 00002110 72D5                <1> 	jc	short dma_bnd_err
  3844                              <1> 	;
  3845 00002112 6629CA              <1> 	sub	dx, cx			; Restore start address
  3846                              <1> 	;
  3847 00002115 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3848 00002117 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3849 00002118 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3850                              <1> 	IODELAY				; WAIT FOR I/O
  2046 0000211A EB00                <2>  jmp short $+2
  2047 0000211C EB00                <2>  jmp short $+2
  3851 0000211E E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3852 00002120 89D0                <1> 	mov	eax,edx			; Buffer address
  3853 00002122 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3854                              <1> 	IODELAY				; WAIT FOR I/O
  2046 00002124 EB00                <2>  jmp short $+2
  2047 00002126 EB00                <2>  jmp short $+2
  3855 00002128 88E0                <1> 	MOV	AL,AH
  3856 0000212A E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3857 0000212C C1E810              <1> 	shr	eax,16
  3858                              <1> 	IODELAY				; I/O WAIT STATE
  2046 0000212F EB00                <2>  jmp short $+2
  2047 00002131 EB00                <2>  jmp short $+2
  3859 00002133 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3860                              <1> 	IODELAY
  2046 00002135 EB00                <2>  jmp short $+2
  2047 00002137 EB00                <2>  jmp short $+2
  3861 00002139 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3862 0000213C E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3863                              <1> 	IODELAY				; WAIT FOR I/O
  2046 0000213E EB00                <2>  jmp short $+2
  2047 00002140 EB00                <2>  jmp short $+2
  3864 00002142 88E0                <1> 	MOV	AL,AH
  3865 00002144 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3866                              <1> 	IODELAY
  2046 00002146 EB00                <2>  jmp short $+2
  2047 00002148 EB00                <2>  jmp short $+2
  3867 0000214A FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3868 0000214B B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3869 0000214D E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3870 0000214F C3                  <1> 	retn
  3871                              <1> 
  3872                              <1> ;; 08/02/2015 - Protected Mode Modification
  3873                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3874                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3875                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3876                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3877                              <1> ;;	IODELAY
  3878                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3879                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3880                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3881                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3882                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3883                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3884                              <1> ;;	;JNC	short J33A
  3885                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3886                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3887                              <1> ;;;J33A:
  3888                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3889                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3890                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3891                              <1> ;;	IODELAY
  3892                              <1> ;;	MOV	AL,AH
  3893                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3894                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3895                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3896                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3897                              <1> ;;	IODELAY
  3898                              <1> ;;	;AND	AL,00001111B
  3899                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3900                              <1> ;;
  3901                              <1> ;;;----- DETERMINE COUNT
  3902                              <1> ;;	sub	eax, eax ; 08/02/2015
  3903                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3904                              <1> ;;	CALL	GET_PARM		; "
  3905                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3906                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3907                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3908                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3909                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3910                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3911                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3912                              <1> ;;	IODELAY
  3913                              <1> ;;	MOV	AL, AH
  3914                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3915                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3916                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  3917                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  3918                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3919                              <1> ;;	add	ecx, eax ; 08/02/2015
  3920                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3921                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3922                              <1> ;;	SIODELAY
  3923                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3924                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  3925                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  3926                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  3927                              <1> ;;	jz	short FMTDMA_OK
  3928                              <1> ;;	stc	; 20/02/2015
  3929                              <1> ;;fmtdma_bnd_err:
  3930                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3931                              <1> ;;FMTDMA_OK:
  3932                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3933                              <1> 
  3934                              <1> ;-------------------------------------------------------------------------------
  3935                              <1> ; NEC_INIT	
  3936                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3937                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3938                              <1> ;
  3939                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3940                              <1> ;
  3941                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3942                              <1> ;-------------------------------------------------------------------------------
  3943                              <1> NEC_INIT:
  3944                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3945                              <1> 	; 24/12/2021
  3946 00002150 50                  <1> 	push	eax
  3947 00002151 E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3948                              <1> 
  3949                              <1> ;-----	DO THE SEEK OPERATION
  3950                              <1> 
  3951 00002156 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  3952 00002159 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  3953                              <1> 	;POP	AX			; RECOVER COMMAND
  3954                              <1> 	; 24/12/2021
  3955 0000215E 58                  <1> 	pop	eax
  3956 0000215F 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  3957 00002161 BB[7F210000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  3958 00002166 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  3959                              <1> 
  3960                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3961                              <1> 
  3962 00002167 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3963 0000216C 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  3964 0000216F 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  3965 00002171 C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  3966 00002174 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  3967 00002177 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  3968 00002179 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3969 0000217E 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  3970                              <1> ER_1:
  3971 0000217F C3                  <1> 	RETn
  3972                              <1> 
  3973                              <1> ;-------------------------------------------------------------------------------
  3974                              <1> ; RWV_COM
  3975                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3976                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3977                              <1> ;
  3978                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3979                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3980                              <1> ;-------------------------------------------------------------------------------
  3981                              <1> RWV_COM:
  3982 00002180 B8[CB210000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  3983 00002185 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3984 00002186 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  3985 00002189 E83E030000          <1> 	CALL	NEC_OUTPUT
  3986 0000218E 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  3987 00002191 E836030000          <1> 	CALL	NEC_OUTPUT
  3988 00002196 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  3989 00002199 E82E030000          <1> 	CALL	NEC_OUTPUT
  3990 0000219E B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3991 000021A0 E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  3992 000021A5 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3993 000021AA B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  3994 000021AC E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  3995 000021B1 E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3996 000021B6 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  3997                              <1> _R15:
  3998 000021B9 E80E030000          <1> 	CALL	NEC_OUTPUT
  3999 000021BE B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4000 000021C0 E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4001 000021C5 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4002 000021CA 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4003                              <1> ER_2:
  4004 000021CB C3                  <1> 	RETn
  4005                              <1> 
  4006                              <1> ;-------------------------------------------------------------------------------
  4007                              <1> ; NEC_TERM
  4008                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4009                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4010                              <1> ;
  4011                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4012                              <1> ;-------------------------------------------------------------------------------
  4013                              <1> NEC_TERM:
  4014                              <1> 
  4015                              <1> ;-----	LET THE OPERATION HAPPEN
  4016                              <1> 
  4017 000021CC 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4018 000021CD E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4019 000021D2 9C                  <1> 	PUSHFd	; 24/12/2021
  4020 000021D3 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4021 000021D8 724B                <1> 	JC	short SET_END_POP
  4022 000021DA 9D                  <1> 	POPFd	; 24/12/2021
  4023 000021DB 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4024                              <1> 
  4025                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4026                              <1> 
  4027 000021DD FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4028 000021DE BE[AD6C0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4029 000021E3 AC                  <1> 	lodsb				; GET ST0
  4030 000021E4 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4031 000021E6 7433                <1> 	JZ	short SET_END
  4032 000021E8 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4033 000021EA 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4034                              <1> 
  4035                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4036                              <1> 
  4037 000021EC AC                  <1> 	lodsb				; GET ST1
  4038 000021ED D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4039 000021EF B404                <1> 	MOV	AH,RECORD_NOT_FND
  4040 000021F1 7222                <1> 	JC	short J19
  4041 000021F3 C0E002              <1> 	SAL	AL,2
  4042 000021F6 B410                <1> 	MOV	AH,BAD_CRC
  4043 000021F8 721B                <1> 	JC	short J19
  4044 000021FA D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4045 000021FC B408                <1> 	MOV	AH,BAD_DMA
  4046 000021FE 7215                <1> 	JC	short J19
  4047 00002200 C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4048 00002203 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4049 00002205 720E                <1> 	JC	short J19
  4050 00002207 D0E0                <1> 	SAL	AL,1
  4051 00002209 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4052 0000220B 7208                <1> 	JC	short J19
  4053 0000220D D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4054 0000220F B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4055 00002211 7202                <1> 	JC	short J19
  4056                              <1> 
  4057                              <1> ;----- 	NEC MUST HAVE FAILED
  4058                              <1> J18:
  4059 00002213 B420                <1> 	MOV	AH,BAD_NEC
  4060                              <1> J19:
  4061 00002215 0825[AC6C0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4062                              <1> SET_END:
  4063 0000221B 803D[AC6C0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4064 00002222 F5                  <1> 	CMC
  4065 00002223 5E                  <1> 	POP	eSI
  4066 00002224 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4067                              <1> 
  4068                              <1> SET_END_POP:
  4069 00002225 9D                  <1> 	POPFd	; 24/12/2021
  4070 00002226 EBF3                <1> 	JMP	SHORT SET_END
  4071                              <1> 
  4072                              <1> ;-------------------------------------------------------------------------------
  4073                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4074                              <1> ;-------------------------------------------------------------------------------
  4075                              <1> DSTATE:
  4076 00002228 803D[AC6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4077 0000222F 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4078 00002231 808F[B96C0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4079 00002238 F687[B96C0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4080 0000223F 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4081 00002241 8A87[B96C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4082 00002247 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4083 00002249 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4084 0000224B 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4085                              <1> 
  4086                              <1> ;----- 	CHECK IF IT IS 1.44M
  4087                              <1> 
  4088 0000224D E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4089                              <1> 	;;20/02/2015
  4090                              <1> 	;;JC	short M_12		; CMOS BAD
  4091 00002252 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4092 00002254 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4093 00002256 7410                <1> 	JE	short M_12		; YES
  4094                              <1> M_720:
  4095 00002258 80A7[B96C0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4096 0000225F 808F[B96C0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4097 00002266 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4098                              <1> M_12:	
  4099 00002268 808F[B96C0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4100                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4101                              <1> SETBAC:
  4102 0000226F C3                  <1> 	RETn
  4103                              <1> 
  4104                              <1> ;-------------------------------------------------------------------------------
  4105                              <1> ; RETRY	
  4106                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4107                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4108                              <1> ;
  4109                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4110                              <1> ;-------------------------------------------------------------------------------
  4111                              <1> RETRY:
  4112 00002270 803D[AC6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4113 00002277 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4114 00002279 803D[AC6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4115 00002280 743C                <1> 	JZ	short NO_RETRY
  4116 00002282 8AA7[B96C0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4117 00002288 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4118 0000228B 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4119 0000228D 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4120 00002290 8A2D[B46C0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4121 00002296 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4122 00002299 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4123 0000229C 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4124 0000229E 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4125                              <1> 
  4126                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4127                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4128                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4129                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4130                              <1> 
  4131 000022A0 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4132 000022A3 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4133 000022A5 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4134 000022A8 80A7[B96C0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4135                              <1> 					; RATE, DBL STEP OFF
  4136 000022AF 08A7[B96C0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4137 000022B5 C605[AC6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4138 000022BC F9                  <1> 	STC				; SET CARRY FOR RETRY
  4139 000022BD C3                  <1> 	RETn				; RETRY RETURN
  4140                              <1> 
  4141                              <1> NO_RETRY:
  4142 000022BE F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4143 000022BF C3                  <1> 	RETn				; NO RETRY RETURN
  4144                              <1> 
  4145                              <1> ;-------------------------------------------------------------------------------
  4146                              <1> ; NUM_TRANS
  4147                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4148                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4149                              <1> ;
  4150                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4151                              <1> ;		SI-HI  = HEAD
  4152                              <1> ;		[BP]   = START SECTOR
  4153                              <1> ;
  4154                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4155                              <1> ;-------------------------------------------------------------------------------
  4156                              <1> NUM_TRANS:
  4157 000022C0 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4158 000022C2 803D[AC6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4159                              <1> 	; 24/12/2021
  4160 000022C9 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4161 000022CB B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4162 000022CD E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4163 000022D2 8A1D[B26C0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4164 000022D8 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4165 000022DB 3A2D[B16C0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4166 000022E1 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4167 000022E3 8A2D[B06C0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4168 000022E9 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4169 000022EC 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4170 000022EE 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4171                              <1> DIF_HD:
  4172 000022F0 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4173                              <1> SAME_TRK:
  4174 000022F2 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4175 000022F5 88D8                <1> 	MOV	AL,BL			; TO AL
  4176                              <1> NT_OUT:
  4177 000022F7 C3                  <1> 	RETn
  4178                              <1> 
  4179                              <1> ;-------------------------------------------------------------------------------
  4180                              <1> ; SETUP_END
  4181                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4182                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4183                              <1> ;
  4184                              <1> ; ON EXIT:
  4185                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4186                              <1> ;-------------------------------------------------------------------------------
  4187                              <1> SETUP_END:
  4188 000022F8 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4189                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4190 000022FA 50                  <1> 	push	eax ; 24/12/2021
  4191 000022FB E8C6000000          <1> 	CALL	GET_PARM
  4192 00002300 8825[AB6C0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4193                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4194 00002306 58                  <1> 	pop	eax ; 24/12/2021
  4195 00002307 8A25[AC6C0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4196 0000230D 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4197 0000230F 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4198 00002311 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4199                              <1> NUN_ERR: 
  4200 00002313 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4201 00002316 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4202 00002317 C3                  <1> 	RETn
  4203                              <1> 
  4204                              <1> ;-------------------------------------------------------------------------------
  4205                              <1> ; SETUP_DBL
  4206                              <1> ;	CHECK DOUBLE STEP.
  4207                              <1> ;
  4208                              <1> ; ON ENTRY :	DI = DRIVE
  4209                              <1> ;
  4210                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4211                              <1> ;-------------------------------------------------------------------------------
  4212                              <1> SETUP_DBL:
  4213 00002318 8AA7[B96C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4214 0000231E F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4215 00002321 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4216                              <1> 
  4217                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4218                              <1> 
  4219 00002323 C605[A96C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4220 0000232A E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4221 0000232F B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4222 00002331 E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4223 00002336 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4224 0000233B 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4225                              <1> 
  4226                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4227                              <1> 
  4228 0000233D 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4229 00002341 F687[B96C0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4230 00002348 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4231 0000234A B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4232                              <1> 
  4233                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4234                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4235                              <1> ;	THEN SET DOUBLE STEP ON.
  4236                              <1> 
  4237                              <1> CNT_OK:
  4238 0000234C C605[AB6C0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4239                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4240                              <1> 	; 24/12/2021
  4241 00002353 51                  <1> 	push	ecx
  4242 00002354 C605[AC6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4243 0000235B 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4244 0000235E D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4245 00002360 C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4246                              <1> 	;PUSH	AX			; SAVE HEAD
  4247                              <1> 	; 24/12/2021
  4248 00002363 50                  <1> 	push	eax
  4249 00002364 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4250                              <1> 	;POP	AX			; RESTORE HEAD
  4251                              <1> 	; 24/12/2021
  4252 00002369 58                  <1> 	pop	eax
  4253 0000236A 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4254 0000236D E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4255 00002372 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4256 00002373 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4257 00002378 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4258                              <1> 	;POP	CX			; RESTORE COUNT
  4259                              <1> 	; 24/12/2021
  4260 00002379 59                  <1> 	pop	ecx
  4261 0000237A 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4262 0000237C FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4263 0000237E 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4264 00002380 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4265                              <1> 
  4266                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4267                              <1> 
  4268                              <1> SD_ERR:	
  4269 00002382 F9                  <1> 	STC				; SET CARRY FOR ERROR
  4270 00002383 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4271                              <1> 
  4272                              <1> DO_CHK:
  4273 00002384 8A0D[B06C0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4274 0000238A 888F[BD6C0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4275 00002390 D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4276 00002392 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4277 00002394 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4278 00002396 808F[B96C0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4279                              <1> NO_DBL:
  4280 0000239D F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4281 0000239E C3                  <1> 	RETn
  4282                              <1> 
  4283                              <1> ;-------------------------------------------------------------------------------
  4284                              <1> ; READ_ID
  4285                              <1> ;	READ ID FUNCTION.
  4286                              <1> ;
  4287                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4288                              <1> ;
  4289                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4290                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4291                              <1> ;-------------------------------------------------------------------------------
  4292                              <1> READ_ID:
  4293 0000239F B8[BC230000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4294 000023A4 50                  <1> 	PUSH	eAX
  4295 000023A5 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4296 000023A7 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4297 000023AC 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4298 000023AF 88C4                <1> 	MOV	AH,AL
  4299 000023B1 E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4300 000023B6 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4301 000023BB 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4302                              <1> ER_3:
  4303 000023BC C3                  <1> 	RETn
  4304                              <1> 
  4305                              <1> ;-------------------------------------------------------------------------------
  4306                              <1> ; CMOS_TYPE
  4307                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4308                              <1> ;
  4309                              <1> ; ON ENTRY:	DI = DRIVE #
  4310                              <1> ;
  4311                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4312                              <1> ;-------------------------------------------------------------------------------
  4313                              <1> 
  4314                              <1> CMOS_TYPE: ; 11/12/2014
  4315 000023BD 8A87[DE660000]      <1> 	mov	al, [eDI+fd0_type]
  4316 000023C3 20C0                <1> 	and 	al, al ; 18/12/2014
  4317 000023C5 C3                  <1> 	retn
  4318                              <1> 
  4319                              <1> ;CMOS_TYPE:
  4320                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4321                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4322                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4323                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4324                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4325                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4326                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4327                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4328                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4329                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4330                              <1> ;TB:
  4331                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4332                              <1> ;BAD_CM:
  4333                              <1> ;	RETn				; CY, STATUS OF READ
  4334                              <1> 
  4335                              <1> ;-------------------------------------------------------------------------------
  4336                              <1> ; GET_PARM
  4337                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4338                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4339                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4340                              <1> ;	THE PARAMETER IN DL.
  4341                              <1> ;
  4342                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4343                              <1> ;
  4344                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4345                              <1> ;		AL,DH DESTROYED
  4346                              <1> ;-------------------------------------------------------------------------------
  4347                              <1> GET_PARM:
  4348                              <1> 	;PUSH	DS
  4349 000023C6 56                  <1> 	PUSH	eSI
  4350                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4351                              <1>     	;MOV	DS,AX
  4352                              <1> 	;;mov	ax, cs
  4353                              <1> 	;;mov	ds, ax
  4354                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4355 000023C7 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4356                              <1> 	;SUB	BH,BH			; BX = INDEX
  4357 000023C9 81E3FF000000        <1> 	and	ebx, 0FFh
  4358                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4359                              <1> 	;
  4360                              <1> 	; 17/12/2014
  4361 000023CF 66A1[D1660000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4362 000023D5 38E0                <1> 	cmp	al, ah
  4363 000023D7 7425                <1> 	je	short gpndc
  4364 000023D9 A2[D2660000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4365 000023DE 53                  <1> 	push	ebx ; 08/02/2015
  4366 000023DF 88C3                <1> 	mov	bl, al 
  4367                              <1> 	; 11/12/2014
  4368 000023E1 8A83[DE660000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4369                              <1> 	; 18/12/2014
  4370 000023E7 20C0                <1> 	and	al, al
  4371 000023E9 7507                <1> 	jnz	short gpdtc
  4372 000023EB BB[BB660000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4373 000023F0 EB05                <1>         jmp     short gpdpu
  4374                              <1> gpdtc:	
  4375 000023F2 E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4376                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4377                              <1> gpdpu:
  4378 000023F7 891D[58660000]      <1> 	mov	[DISK_POINTER], ebx
  4379 000023FD 5B                  <1> 	pop	ebx
  4380                              <1> gpndc:
  4381 000023FE 8B35[58660000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4382 00002404 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4383 00002407 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4384 00002409 5E                  <1> 	POP	eSI
  4385                              <1> 	;POP	DS
  4386 0000240A C3                  <1> 	RETn
  4387                              <1> 
  4388                              <1> ;-------------------------------------------------------------------------------
  4389                              <1> ; MOTOR_ON
  4390                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4391                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4392                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4393                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4394                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4395                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4396                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4397                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4398                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4399                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4400                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4401                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4402                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4403                              <1> ;
  4404                              <1> ; ON ENTRY:	DI = DRIVE #
  4405                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4406                              <1> ;-------------------------------------------------------------------------------
  4407                              <1> MOTOR_ON:
  4408 0000240B 53                  <1> 	PUSH	eBX			; SAVE REG.
  4409 0000240C E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4410 00002411 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4411 00002413 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4412 00002418 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4413                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4414                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4415                              <1> M_WAIT:
  4416 0000241D B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4417 0000241F E8A2FFFFFF          <1> 	CALL	GET_PARM
  4418                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4419                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4420                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4421 00002424 80FC08              <1> 	cmp	ah, 8
  4422                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4423 00002427 7702                <1> 	ja	short J13
  4424                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4425 00002429 B408                <1> 	mov	ah, 8
  4426                              <1> 
  4427                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4428                              <1> GP2:	
  4429                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4430                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4431 0000242B B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4432 00002430 E862F1FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4433                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4434 00002435 FECC                <1> 	dec	ah
  4435 00002437 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4436                              <1> MOT_IS_ON:
  4437 00002439 5B                  <1> 	POP	eBX			; RESTORE REG.
  4438 0000243A C3                  <1> 	RETn
  4439                              <1> 
  4440                              <1> ;-------------------------------------------------------------------------------
  4441                              <1> ; TURN_ON
  4442                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4443                              <1> ;
  4444                              <1> ; ON ENTRY:	DI = DRIVE #
  4445                              <1> ;
  4446                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4447                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4448                              <1> ;		AX,BX,CX,DX DESTROYED
  4449                              <1> ;-------------------------------------------------------------------------------
  4450                              <1> TURN_ON:
  4451 0000243B 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4452 0000243D 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4453 0000243F C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4454 00002442 FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4455 00002443 C605[AB6C0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4456 0000244A A0[AA6C0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4457 0000244F 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4458 00002451 B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4459 00002453 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4460                              <1> 
  4461                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4462                              <1> ;  BL = DRIVE SELECT DESIRED
  4463                              <1> ;  AH = MOTOR ON MASK DESIRED
  4464                              <1> 
  4465 00002455 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4466 00002457 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4467 00002459 8425[AA6C0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4468 0000245F 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4469                              <1> 
  4470                              <1> TURN_IT_ON:
  4471 00002461 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4472 00002463 8A3D[AA6C0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4473 00002469 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4474 0000246C 8025[AA6C0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4475 00002473 0825[AA6C0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4476 00002479 A0[AA6C0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4477 0000247E 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4478 00002480 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4479 00002483 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4480 00002484 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4481 00002486 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4482 00002489 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4483 0000248B 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4484 0000248F EE                  <1> 	OUT	DX,AL
  4485 00002490 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4486                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4487 00002492 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4488 00002494 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4489 00002495 C3                  <1> 	RETn
  4490                              <1> 
  4491                              <1> NO_MOT_WAIT:
  4492 00002496 FB                  <1> 	sti
  4493                              <1> no_mot_w1: ; 27/02/2015
  4494 00002497 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4495                              <1> 	;STI				; INTERRUPTS BACK ON
  4496 00002498 C3                  <1> 	RETn
  4497                              <1> 
  4498                              <1> ;-------------------------------------------------------------------------------
  4499                              <1> ; HD_WAIT
  4500                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4501                              <1> ;
  4502                              <1> ; ON ENTRY:	DI = DRIVE #
  4503                              <1> ;
  4504                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4505                              <1> ;-------------------------------------------------------------------------------
  4506                              <1> HD_WAIT:
  4507 00002499 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4508 0000249B E826FFFFFF          <1> 	CALL	GET_PARM
  4509 000024A0 08E4                <1> 	or	ah, ah	; 17/12/2014
  4510 000024A2 7519                <1> 	jnz	short DO_WAT
  4511 000024A4 F605[AA6C0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4512                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4513                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4514                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4515 000024AB 741E                <1> 	jz	short HW_DONE
  4516 000024AD B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4517 000024AF 8A87[B96C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4518 000024B5 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4519 000024B7 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4520 000024B9 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4521                              <1> ;GP3:
  4522 000024BB B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4523                              <1> ;	JMP	SHORT DO_WAT
  4524                              <1> 
  4525                              <1> ;ISNT_WRITE:
  4526                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4527                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4528                              <1> 
  4529                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4530                              <1> DO_WAT:
  4531                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4532                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4533                              <1> J29:					; 	1 MILLISECOND LOOP
  4534                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4535 000024BD B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4536 000024C2 E8D0F0FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4537                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4538 000024C7 FECC                <1> 	dec	ah
  4539 000024C9 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4540                              <1> HW_DONE:
  4541 000024CB C3                  <1> 	RETn
  4542                              <1> 
  4543                              <1> ;-------------------------------------------------------------------------------
  4544                              <1> ; NEC_OUTPUT
  4545                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4546                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4547                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4548                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4549                              <1> ; 
  4550                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4551                              <1> ;
  4552                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4553                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4554                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4555                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4556                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4557                              <1> ;		AX,CX,DX DESTROYED
  4558                              <1> ;-------------------------------------------------------------------------------
  4559                              <1> 
  4560                              <1> ; 09/12/2014 [Erdogan Tan] 
  4561                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4562                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4563                              <1> ;	This read only register facilitates the transfer of data between
  4564                              <1> ;	the system microprocessor and the controller.
  4565                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4566                              <1> ;	  with the system micrprocessor.
  4567                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4568                              <1> ;	  the transfer is to the controller.
  4569                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4570                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4571                              <1> ; Bit 3 - Reserved.
  4572                              <1> ; Bit 2 - Reserved.
  4573                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4574                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4575                              <1> 
  4576                              <1> ; Data Register (3F5h)
  4577                              <1> ; This read/write register passes data, commands and parameters, and provides
  4578                              <1> ; diskette status information.
  4579                              <1>   		
  4580                              <1> NEC_OUTPUT:
  4581                              <1> 	;PUSH	BX			; SAVE REG.
  4582 000024CC 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4583                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4584                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4585                              <1> 	; 16/12/2014
  4586                              <1> 	; waiting for (max.) 0.5 seconds
  4587                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4588                              <1> 	;
  4589                              <1> 	; 17/12/2014
  4590                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4591                              <1> 	;
  4592                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4593                              <1> 	;		go on.
  4594                              <1> 	;INPUT:
  4595                              <1> 	;	AH=Mask for isolation bits.
  4596                              <1> 	;	AL=pattern to look for.
  4597                              <1> 	;	DX=Port to test for
  4598                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4599                              <1> 	;	     (normally 30 microseconds per period.)
  4600                              <1> 	;
  4601                              <1> 	;WFP_SHORT:  
  4602                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4603                              <1> 	;
  4604                              <1> 
  4605                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4606                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4607 000024D0 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4608                              <1> ;
  4609                              <1> ;WFPS_OUTER_LP:
  4610                              <1> ;	;
  4611                              <1> ;WFPS_CHECK_PORT:
  4612                              <1> J23:
  4613 000024D5 EC                  <1> 	IN	AL,DX			; GET STATUS
  4614 000024D6 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4615 000024D8 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4616 000024DA 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4617                              <1> WFPS_HI:
  4618 000024DC E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4619 000024DE A810                <1> 	TEST	AL,010H			; transition on memory
  4620 000024E0 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4621                              <1> WFPS_LO:
  4622 000024E2 E461                <1> 	IN	AL, PORT_B		; SYS1
  4623 000024E4 A810                <1> 	TEST	AL,010H
  4624 000024E6 74FA                <1> 	JZ	SHORT WFPS_LO
  4625                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4626 000024E8 E2EB                <1> 	loop	J23	; 27/02/2015
  4627                              <1> ;	;
  4628                              <1> ;	dec	bl
  4629                              <1> ;	jnz	short WFPS_OUTER_LP
  4630                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4631                              <1> ;J23:
  4632                              <1> ;	IN	AL,DX			; GET STATUS
  4633                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4634                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4635                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4636                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4637                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4638                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4639                              <1>    
  4640                              <1> 	;;27/02/2015
  4641                              <1> 	;16/12/2014
  4642                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4643                              <1> 	;;jb	short J23
  4644                              <1> 
  4645                              <1> ;WFPS_TIMEOUT:
  4646                              <1> 
  4647                              <1> ;-----	FALL THRU TO ERROR RETURN
  4648                              <1> 
  4649 000024EA 800D[AC6C0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4650                              <1> 	;POP	BX			; RESTORE REG.
  4651 000024F1 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4652 000024F2 F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4653 000024F3 C3                  <1> 	RETn
  4654                              <1> 
  4655                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4656                              <1> 
  4657                              <1> J27:	
  4658 000024F4 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4659 000024F6 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4660 000024F8 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4661                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4662                              <1> 	; 27/02/2015
  4663 000024F9 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4664                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4665 000024FA 29C9                <1> 	sub	ecx, ecx
  4666 000024FC B103                <1> 	mov	cl, 3 ; 24/12/2021
  4667 000024FE E894F0FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4668 00002503 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4669                              <1> 	;POP	BX			; RESTORE REG
  4670 00002504 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4671                              <1> 
  4672                              <1> ;-------------------------------------------------------------------------------
  4673                              <1> ; SEEK
  4674                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4675                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4676                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4677                              <1> ;
  4678                              <1> ; ON ENTRY:	DI = DRIVE #
  4679                              <1> ;		CH = TRACK #
  4680                              <1> ;
  4681                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4682                              <1> ;		AX,BX,CX DX DESTROYED
  4683                              <1> ;-------------------------------------------------------------------------------
  4684                              <1> SEEK:
  4685 00002505 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4686 00002507 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4687 00002509 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4688 0000250B D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4689 0000250D 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4690 0000250F 8405[A96C0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4691 00002515 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4692                              <1> 
  4693 00002517 0805[A96C0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4694 0000251D E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4695 00002522 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4696                              <1> 
  4697                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4698                              <1> 
  4699 00002524 C605[AC6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4700 0000252B E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4701 00002530 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4702                              <1> 
  4703                              <1> AFT_RECAL:
  4704 00002532 C687[BD6C0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4705 00002539 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4706 0000253B 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4707                              <1> 
  4708                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4709                              <1> 
  4710 0000253D F687[B96C0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4711 00002544 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4712 00002546 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4713                              <1> 
  4714 00002548 3AAF[BD6C0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4715 0000254E 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4716                              <1> 
  4717 00002550 BA[83250000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4718 00002555 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4719 00002556 88AF[BD6C0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4720 0000255C B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4721 0000255E E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4722 00002563 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4723 00002565 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4724 00002567 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4725 0000256C 8AA7[BD6C0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4726 00002572 E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4727 00002577 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4728                              <1> 
  4729                              <1> ;-----	WAIT FOR HEAD SETTLE
  4730                              <1> 
  4731                              <1> DO_WAIT:
  4732 0000257C 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4733 0000257D E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4734 00002582 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4735                              <1> RB:
  4736                              <1> NEC_ERR:
  4737                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4738                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4739 00002583 C3                  <1> 	RETn				; RETURN TO CALLER
  4740                              <1> 
  4741                              <1> ;-------------------------------------------------------------------------------
  4742                              <1> ; RECAL
  4743                              <1> ;	RECALIBRATE DRIVE
  4744                              <1> ;
  4745                              <1> ; ON ENTRY:	DI = DRIVE #
  4746                              <1> ;
  4747                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4748                              <1> ;-------------------------------------------------------------------------------
  4749                              <1> RECAL:
  4750                              <1> 	;PUSH	CX
  4751                              <1> 	; 24/12/2021
  4752 00002584 51                  <1> 	push	ecx
  4753 00002585 B8[A1250000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4754 0000258A 50                  <1> 	PUSH	eAX
  4755 0000258B B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4756 0000258D E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4757 00002592 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4758 00002594 88DC                <1> 	MOV	AH,BL
  4759 00002596 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4760 0000259B E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4761 000025A0 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4762                              <1> RC_BACK:
  4763                              <1> 	;POP	CX
  4764                              <1> 	; 24/12/2021
  4765 000025A1 59                  <1> 	pop	ecx
  4766 000025A2 C3                  <1> 	RETn
  4767                              <1> 
  4768                              <1> ;-------------------------------------------------------------------------------
  4769                              <1> ; CHK_STAT_2
  4770                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4771                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4772                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4773                              <1> ;
  4774                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4775                              <1> ;-------------------------------------------------------------------------------
  4776                              <1> CHK_STAT_2:
  4777 000025A3 B8[CB250000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4778 000025A8 50                  <1> 	PUSH	eAX
  4779 000025A9 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4780 000025AE 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4781 000025B0 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4782 000025B2 E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4783 000025B7 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4784 000025BC 720C                <1> 	JC	short J34
  4785 000025BE A0[AD6C0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4786 000025C3 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4787 000025C5 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4788 000025C7 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4789 000025C9 F8                  <1> 	CLC				; GOOD RETURN
  4790                              <1> J34:
  4791 000025CA 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4792                              <1> CS_BACK:
  4793 000025CB C3                  <1> 	RETn
  4794                              <1> J35:
  4795 000025CC 800D[AC6C0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4796 000025D3 F9                  <1> 	STC				; ERROR RETURN CODE
  4797 000025D4 EBF4                <1> 	JMP	SHORT J34
  4798                              <1> 
  4799                              <1> ;-------------------------------------------------------------------------------
  4800                              <1> ; WAIT_INT
  4801                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4802                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4803                              <1> ;	IF THE DRIVE IS NOT READY.
  4804                              <1> ;
  4805                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4806                              <1> ;-------------------------------------------------------------------------------
  4807                              <1> 
  4808                              <1> ; 17/12/2014
  4809                              <1> ; 2.5 seconds waiting !
  4810                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4811                              <1> ; amount of time to wait for completion interrupt from NEC.
  4812                              <1> 
  4813                              <1> 
  4814                              <1> WAIT_INT:
  4815 000025D6 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4816 000025D7 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4817                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4818                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4819                              <1> 
  4820                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4821                              <1> 	;
  4822                              <1> 	;WAIT_FOR_MEM:	
  4823                              <1> 	;	Waits for a bit at a specified memory location pointed
  4824                              <1> 	;	to by ES:[DI] to become set.
  4825                              <1> 	;INPUT:
  4826                              <1> 	;	AH=Mask to test with.
  4827                              <1> 	;	ES:[DI] = memory location to watch.
  4828                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4829                              <1> 	;	     (normally 30 microseconds per period.)
  4830                              <1> 
  4831                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4832                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4833                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4834                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4835                              <1> 	; 27/02/2015
  4836 000025D8 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4837                              <1> WFMS_CHECK_MEM:
  4838 000025DD F605[A96C0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4839 000025E4 7516                <1>         jnz     short J37
  4840                              <1> WFMS_HI:
  4841 000025E6 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4842 000025E8 A810                <1> 	TEST	AL,010H			; transition on memory
  4843 000025EA 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4844                              <1> WFMS_LO:
  4845 000025EC E461                <1> 	IN	AL,PORT_B		;SYS1
  4846 000025EE A810                <1> 	TEST	AL,010H
  4847 000025F0 74FA                <1> 	JZ	SHORT WFMS_LO
  4848 000025F2 E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4849                              <1> ;WFMS_OUTER_LP:
  4850                              <1> ;;	or	bl, bl			; check outer counter
  4851                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4852                              <1> ;	dec	bl
  4853                              <1> ;	jz	short J36A	
  4854                              <1> ;	jmp	short WFMS_CHECK_MEM
  4855                              <1> 
  4856                              <1> 	;17/12/2014
  4857                              <1> 	;16/12/2014
  4858                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4859                              <1> ;J36:
  4860                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4861                              <1> ;	JNZ	short J37
  4862                              <1> 	;16/12/2014
  4863                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4864                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4865                              <1> 	;JNZ	short J36
  4866                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4867                              <1> ;	jb	short J36
  4868                              <1> 
  4869                              <1> ;WFMS_TIMEOUT:
  4870                              <1> ;J36A:
  4871 000025F4 800D[AC6C0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4872 000025FB F9                  <1> 	STC				; ERROR RETURN
  4873                              <1> J37:
  4874 000025FC 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4875 000025FD 8025[A96C0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4876 00002604 9D                  <1> 	POPF				; RECOVER CARRY
  4877 00002605 C3                  <1> 	RETn				; GOOD RETURN CODE
  4878                              <1> 
  4879                              <1> ;-------------------------------------------------------------------------------
  4880                              <1> ; RESULTS
  4881                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4882                              <1> ;	FOLLOWING AN INTERRUPT.
  4883                              <1> ;
  4884                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4885                              <1> ;		AX,BX,CX,DX DESTROYED
  4886                              <1> ;-------------------------------------------------------------------------------
  4887                              <1> RESULTS:
  4888 00002606 57                  <1> 	PUSH	eDI
  4889 00002607 BF[AD6C0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4890 0000260C B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4891 0000260E 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4892                              <1> 
  4893                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4894                              <1> 
  4895                              <1> _R10: 
  4896                              <1> 	; 16/12/2014
  4897                              <1> 	; wait for (max) 0.5 seconds
  4898                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4899                              <1> 	;XOR	CX,CX			; COUNTER
  4900                              <1> 
  4901                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4902                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4903                              <1> 	; 27/02/2015
  4904 00002612 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4905                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4906                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4907                              <1> 
  4908                              <1> WFPSR_OUTER_LP:
  4909                              <1> 	;
  4910                              <1> WFPSR_CHECK_PORT:
  4911                              <1> J39:					; WAIT FOR MASTER
  4912 00002617 EC                  <1> 	IN	AL,DX			; GET STATUS
  4913 00002618 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4914 0000261A 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4915 0000261C 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  4916                              <1> WFPSR_HI:
  4917 0000261E E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4918 00002620 A810                <1> 	TEST	AL,010H			; transition on memory
  4919 00002622 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  4920                              <1> WFPSR_LO:
  4921 00002624 E461                <1> 	IN	AL, PORT_B		; SYS1
  4922 00002626 A810                <1> 	TEST	AL,010H
  4923 00002628 74FA                <1> 	JZ	SHORT WFPSR_LO
  4924 0000262A E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  4925                              <1> 	;; 27/02/2015
  4926                              <1> 	;;dec	bh
  4927                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4928                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4929                              <1> 
  4930                              <1> 	;;mov	byte [wait_count], 0
  4931                              <1> ;J39:					; WAIT FOR MASTER
  4932                              <1> ;	IN	AL,DX			; GET STATUS
  4933                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4934                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4935                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  4936                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  4937                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  4938                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  4939                              <1> 	;
  4940                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  4941                              <1> 	;;jb	short J39	
  4942                              <1> 
  4943                              <1> ;WFPSR_TIMEOUT:
  4944 0000262C 800D[AC6C0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4945 00002633 F9                  <1> 	STC				; SET ERROR RETURN
  4946 00002634 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  4947                              <1> 
  4948                              <1> ;-----	READ IN THE STATUS
  4949                              <1> 
  4950                              <1> J42:
  4951 00002636 EB00                <1> 	JMP	$+2			; I/O DELAY
  4952 00002638 6642                <1> 	INC	DX			; POINT AT DATA PORT
  4953 0000263A EC                  <1> 	IN	AL,DX			; GET THE DATA
  4954                              <1> 	; 16/12/2014
  4955                              <1> 	NEWIODELAY
  2051 0000263B E6EB                <2>  out 0EBh,al
  4956 0000263D 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  4957 0000263F 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  4958                              <1> 	; 16/12/2014
  4959                              <1> ;	push	cx
  4960                              <1> ;	mov	cx, 30
  4961                              <1> ;wdw2:
  4962                              <1> ;	NEWIODELAY
  4963                              <1> ;	loop	wdw2
  4964                              <1> ;	pop	cx
  4965                              <1> 
  4966 00002640 B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4967 00002645 E84DEFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4968 0000264A 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  4969 0000264C EC                  <1> 	IN	AL,DX			; GET STATUS
  4970                              <1> 	; 16/12/2014
  4971                              <1> 	NEWIODELAY
  2051 0000264D E6EB                <2>  out 0EBh,al
  4972                              <1> 	;
  4973 0000264F A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  4974 00002651 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  4975                              <1> 
  4976 00002653 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  4977 00002655 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  4978 00002657 800D[AC6C0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  4979 0000265E F9                  <1> 	STC				; SET ERROR FLAG
  4980                              <1> 
  4981                              <1> ;-----	RESULT OPERATION IS DONE
  4982                              <1> POPRES:
  4983 0000265F 5F                  <1> 	POP	eDI
  4984 00002660 C3                  <1> 	RETn				; RETURN WITH CARRY SET
  4985                              <1> 
  4986                              <1> ;-------------------------------------------------------------------------------
  4987                              <1> ; READ_DSKCHNG
  4988                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4989                              <1> ;
  4990                              <1> ; ON ENTRY:	DI = DRIVE #
  4991                              <1> ;
  4992                              <1> ; ON EXIT:	DI = DRIVE #
  4993                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4994                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4995                              <1> ;		AX,CX,DX DESTROYED
  4996                              <1> ;-------------------------------------------------------------------------------
  4997                              <1> READ_DSKCHNG:
  4998 00002661 E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4999 00002666 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5000 0000266A EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5001 0000266B A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5002 0000266D C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5003                              <1> 
  5004                              <1> ;-------------------------------------------------------------------------------
  5005                              <1> ; DRIVE_DET
  5006                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5007                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5008                              <1> ; ON ENTRY:	DI = DRIVE #
  5009                              <1> ;-------------------------------------------------------------------------------
  5010                              <1> DRIVE_DET:
  5011 0000266E E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5012 00002673 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5013 00002678 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5014 0000267A B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5015 0000267C E884FEFFFF          <1> 	CALL	SEEK
  5016 00002681 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5017 00002683 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5018                              <1> SK_GIN:
  5019 00002685 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5020                              <1> 	;PUSH	CX			; SAVE TRACK
  5021                              <1> 	; 24/12/2021
  5022 00002687 51                  <1> 	push	ecx
  5023 00002688 E878FEFFFF          <1> 	CALL	SEEK
  5024 0000268D 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5025 0000268F B8[CA260000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5026 00002694 50                  <1> 	PUSH	eAX
  5027 00002695 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5028 00002697 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5029 0000269C 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5030 0000269F 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5031 000026A1 E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5032 000026A6 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5033 000026AB 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5034                              <1> 	;POP	CX			; RESTORE TRACK
  5035                              <1> 	; 24/12/2021
  5036 000026AC 59                  <1> 	pop	ecx
  5037 000026AD F605[AD6C0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5038 000026B4 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5039 000026B6 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5040 000026B8 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5041                              <1> 
  5042                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5043                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5044                              <1> 
  5045 000026BA 808F[B96C0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5046 000026C1 C3                  <1> 	RETn				; ALL INFORMATION SET
  5047                              <1> IS_80:
  5048 000026C2 808F[B96C0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5049                              <1> DD_BAC:
  5050 000026C9 C3                  <1> 	RETn
  5051                              <1> POP_BAC:
  5052                              <1> 	;POP	CX			; THROW AWAY
  5053                              <1> 	; 24/12/2021
  5054 000026CA 59                  <1> 	pop	ecx
  5055 000026CB C3                  <1> 	RETn
  5056                              <1> 
  5057                              <1> fdc_int:  
  5058                              <1> 	  ; 30/07/2015	
  5059                              <1> 	  ; 16/02/2015
  5060                              <1> ;int_0Eh: ; 11/12/2014
  5061                              <1> 
  5062                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5063                              <1> ; DISK_INT
  5064                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5065                              <1> ;
  5066                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5067                              <1> ;-------------------------------------------------------------------------------
  5068                              <1> DISK_INT_1:
  5069                              <1> 
  5070                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5071                              <1> 	; 24/12/2021
  5072 000026CC 50                  <1> 	push	eax
  5073 000026CD 1E                  <1> 	push	ds
  5074 000026CE 66B81000            <1> 	mov	ax, KDATA
  5075 000026D2 8ED8                <1> 	mov 	ds, ax
  5076 000026D4 800D[A96C0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5077 000026DB B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5078 000026DD E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5079 000026DF 1F                  <1> 	pop	ds
  5080                              <1> 	;POP	AX			; RECOVER REGISTER
  5081                              <1> 	; 24/12/2021
  5082 000026E0 58                  <1> 	pop	eax
  5083 000026E1 CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5084                              <1> 
  5085                              <1> ;-------------------------------------------------------------------------------
  5086                              <1> ; DSKETTE_SETUP
  5087                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5088                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5089                              <1> ;-------------------------------------------------------------------------------
  5090                              <1> DSKETTE_SETUP:
  5091                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5092                              <1> 	;PUSH	BX
  5093                              <1> 	;PUSH	CX
  5094 000026E2 52                  <1> 	PUSH	eDX
  5095                              <1> 	;PUSH	DI
  5096                              <1> 	;;PUSH	DS
  5097                              <1> 	; 14/12/2014
  5098                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5099                              <1> 	;mov	[DISK_POINTER+2], cs
  5100                              <1> 	;
  5101                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5102 000026E3 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5103 000026E5 66C705[B96C0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5103 000026ED 00                  <1>
  5104 000026EE 8025[B46C0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5105 000026F5 800D[B46C0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5106 000026FC C605[A96C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5107 00002703 C605[AB6C0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5108 0000270A C605[AA6C0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5109 00002711 C605[AC6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5110                              <1> 	;
  5111                              <1> 	; 28/02/2015
  5112                              <1> 	;mov	word [cfd], 100h 
  5113 00002718 E89DF2FFFF          <1> 	call	DSK_RESET
  5114 0000271D 5A                  <1> 	pop	edx
  5115 0000271E C3                  <1> 	retn
  5116                              <1> 
  5117                              <1> ;SUP0:
  5118                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5119                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5120                              <1> ;	; 02/01/2015
  5121                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5122                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5123                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5124                              <1> ;       cmp     byte [fd1_type], 0	
  5125                              <1> ;	jna	short sup1
  5126                              <1> ;	or	di, di
  5127                              <1> ;	jnz	short sup1
  5128                              <1> ;	inc	di
  5129                              <1> ;       jmp     short SUP0
  5130                              <1> ;sup1:
  5131                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5132                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5133                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5134                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5135                              <1> ;	;POP	DI
  5136                              <1> ;	POP	eDX
  5137                              <1> ;	;POP	CX
  5138                              <1> ;	;POP	BX
  5139                              <1> ;	;POP	AX
  5140                              <1> ;	RETn
  5141                              <1> 
  5142                              <1> ;//////////////////////////////////////////////////////
  5143                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5144                              <1> ;
  5145                              <1> 
  5146                              <1> int13h: ; 21/02/2015
  5147 0000271F 9C                  <1> 	pushfd
  5148 00002720 0E                  <1> 	push 	cs
  5149 00002721 E859000000          <1> 	call 	DISK_IO
  5150 00002726 C3                  <1> 	retn
  5151                              <1> 
  5152                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5153                              <1> ;/////////////////////////////////////////////////////////////////////
  5154                              <1> 
  5155                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5156                              <1> ; 23/02/2015
  5157                              <1> ; 21/02/2015 (unix386.s)
  5158                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5159                              <1> ;
  5160                              <1> ; Original Source Code:
  5161                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5162                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5163                              <1> ;
  5164                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5165                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5166                              <1> ;
  5167                              <1> 
  5168                              <1> ;The wait for controller to be not busy is 10 seconds.
  5169                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5170                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5171                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5172                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5173                              <1> 
  5174                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5175                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5176                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5177                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5178                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5179                              <1> 
  5180                              <1> ;The wait for Data request on read and write longs is
  5181                              <1> ;2000 us. (?)
  5182                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5183                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5184                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5185                              <1> 
  5186                              <1> ; Port 61h (PORT_B)
  5187                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5188                              <1> 
  5189                              <1> ; 23/12/2014
  5190                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5191                              <1> 
  5192                              <1> ;--- INT 13H -------------------------------------------------------------------
  5193                              <1> ;									       :
  5194                              <1> ; FIXED DISK I/O INTERFACE						       :
  5195                              <1> ;									       :
  5196                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5197                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5198                              <1> ;									       :
  5199                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5200                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5201                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5202                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5203                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5204                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5205                              <1> ;									       :
  5206                              <1> ;------------------------------------------------------------------------------:
  5207                              <1> ;									       :
  5208                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5209                              <1> ;									       :
  5210                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5211                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5212                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5213                              <1> ;			  DL > 80H - DISK				       :
  5214                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5215                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5216                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5217                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5218                              <1> ;	(AH)= 06H  UNUSED						       :
  5219                              <1> ;	(AH)= 07H  UNUSED						       :
  5220                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5221                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5222                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5223                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5224                              <1> ;	(AH)= 0AH  READ LONG						       :
  5225                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5226                              <1> ;	(AH)= 0CH  SEEK 						       :
  5227                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5228                              <1> ;	(AH)= 0EH  UNUSED						       :
  5229                              <1> ;	(AH)= 0FH  UNUSED						       :
  5230                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5231                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5232                              <1> ;	(AH)= 12H  UNUSED						       :
  5233                              <1> ;	(AH)= 13H  UNUSED						       :
  5234                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5235                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5236                              <1> ;									       :
  5237                              <1> ;-------------------------------------------------------------------------------
  5238                              <1> ;									       :
  5239                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5240                              <1> ;									       :
  5241                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5242                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5243                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5244                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5245                              <1> ;									       :
  5246                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5247                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5248                              <1> ;				 (10 BITS TOTAL)			       :
  5249                              <1> ;									       :
  5250                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5251                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5252                              <1> ;									       :
  5253                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5254                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5255                              <1> ;									       :
  5256                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5257                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5258                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5259                              <1> ;			       80H FOR A BAD SECTOR			       :
  5260                              <1> ;			   N = SECTOR NUMBER				       :
  5261                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5262                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5263                              <1> ;									       :
  5264                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5265                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5266                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5267                              <1> ;									       :
  5268                              <1> ;-------------------------------------------------------------------------------
  5269                              <1> 
  5270                              <1> ;-------------------------------------------------------------------------------
  5271                              <1> ; OUTPUT								       :
  5272                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5273                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5274                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5275                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5276                              <1> ;									       :
  5277                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5278                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5279                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5280                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5281                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5282                              <1> ;		REWRITTEN.						       :
  5283                              <1> ;									       :
  5284                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5285                              <1> ;	   INPUT:							       :
  5286                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5287                              <1> ;	   OUTPUT:							       :
  5288                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5289                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5290                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5291                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5292                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5293                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5294                              <1> ;									       :
  5295                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5296                              <1> ;									       :
  5297                              <1> ;	AH = 0 - NOT PRESENT						       :
  5298                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5299                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5300                              <1> ;	     3 - FIXED DISK						       :
  5301                              <1> ;									       :
  5302                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5303                              <1> ;									       :
  5304                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5305                              <1> ;	INFORMATION.							       :
  5306                              <1> ;									       :
  5307                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5308                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5309                              <1> ;									       :
  5310                              <1> ;-------------------------------------------------------------------------------
  5311                              <1> 
  5312                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5313                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5314                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5315                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5316                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5317                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5318                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5319                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5320                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5321                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5322                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5323                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5324                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5325                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5326                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5327                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5328                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5329                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5330                              <1> 
  5331                              <1> ;--------------------------------------------------------
  5332                              <1> ;							:
  5333                              <1> ; FIXED DISK PARAMETER TABLE				:
  5334                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5335                              <1> ;							:
  5336                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5337                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5338                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5339                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5340                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5341                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5342                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5343                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5344                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5345                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5346                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5347                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5348                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5349                              <1> ;							:
  5350                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5351                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5352                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5353                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5354                              <1> ;							:
  5355                              <1> ;--------------------------------------------------------
  5356                              <1> 
  5357                              <1> ;--------------------------------------------------------
  5358                              <1> ;							:
  5359                              <1> ; HARDWARE SPECIFIC VALUES				:
  5360                              <1> ;							:
  5361                              <1> ;  -  CONTROLLER I/O PORT				:
  5362                              <1> ;							:
  5363                              <1> ;     > WHEN READ FROM: 				:
  5364                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5365                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5366                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5367                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5368                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5369                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5370                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5371                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5372                              <1> ;							:
  5373                              <1> ;     > WHEN WRITTEN TO:				:
  5374                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5375                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5376                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5377                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5378                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5379                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5380                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5381                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5382                              <1> ;							:
  5383                              <1> ;--------------------------------------------------------
  5384                              <1> 
  5385                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5386                              <1> ;HF1_PORT	equ	0170h	
  5387                              <1> ;HF_REG_PORT	EQU	03F6H
  5388                              <1> ;HF1_REG_PORT	equ	0376h
  5389                              <1> 
  5390                              <1> HDC1_BASEPORT	equ	1F0h
  5391                              <1> HDC2_BASEPORT	equ	170h		
  5392                              <1> 
  5393 00002727 90                  <1> align 2
  5394                              <1> 
  5395                              <1> ;-----		STATUS REGISTER
  5396                              <1> 
  5397                              <1> ST_ERROR	EQU	00000001B	;
  5398                              <1> ST_INDEX	EQU	00000010B	;
  5399                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5400                              <1> ST_DRQ		EQU	00001000B	;
  5401                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5402                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5403                              <1> ST_READY	EQU	01000000B	;
  5404                              <1> ST_BUSY 	EQU	10000000B	;
  5405                              <1> 
  5406                              <1> ;-----		ERROR REGISTER
  5407                              <1> 
  5408                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5409                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5410                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5411                              <1> ;		EQU	00001000B	; NOT USED
  5412                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5413                              <1> ;		EQU	00100000B	; NOT USED
  5414                              <1> ERR_DATA_ECC	EQU	01000000B
  5415                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5416                              <1> 
  5417                              <1> 
  5418                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5419                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5420                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5421                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5422                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5423                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5424                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5425                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5426                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5427                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5428                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5429                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5430                              <1> 
  5431                              <1> ;MAX_FILE	EQU	2
  5432                              <1> ;S_MAX_FILE	EQU	2
  5433                              <1> MAX_FILE	equ	4		; 22/12/2014
  5434                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5435                              <1> 
  5436                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5437                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5438                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5439                              <1> 
  5440                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5441                              <1> 
  5442                              <1> ;-----		COMMAND BLOCK REFERENCE
  5443                              <1> 
  5444                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5445                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5446                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5447                              <1> ; 19/12/2014
  5448                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5449                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5450                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5451                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5452                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5453                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5454                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5455                              <1> 
  5456                              <1> align 2
  5457                              <1> 
  5458                              <1> ;----------------------------------------------------------------
  5459                              <1> ; FIXED DISK I/O SETUP						:
  5460                              <1> ;								:
  5461                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5462                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5463                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5464                              <1> ;								:
  5465                              <1> ;----------------------------------------------------------------
  5466                              <1> 
  5467                              <1> DISK_SETUP:
  5468                              <1> 	;CLI
  5469                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5470                              <1> 	;xor	ax,ax
  5471                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5472                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5473                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5474                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5475                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5476                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5477                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5478                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5479                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5480                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5481                              <1> 	;;MOV	[HDISK_INT+2],CS
  5482                              <1> 	;mov	[HDISK_INT1+2],CS
  5483                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5484                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5485                              <1> 	;mov	[HDISK_INT2+2],CS
  5486                              <1> 	;
  5487                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5488                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5489                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5490                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5491                              <1> 	;push	cs
  5492                              <1> 	;pop	ds
  5493                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5494                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5495 00002728 C705[C46C0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5495 00002730 0900                <1>
  5496                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5497                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5498 00002732 C705[C86C0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5498 0000273A 0900                <1>
  5499                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5500                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5501 0000273C C705[CC6C0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5501 00002744 0900                <1>
  5502                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5503                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5504 00002746 C705[D06C0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5504 0000274E 0900                <1>
  5505                              <1> 	;
  5506                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5507                              <1> 	;;;AND	AL,0BFH
  5508                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5509                              <1> 	;;;JMP	$+2
  5510                              <1> 	;;IODELAY
  5511                              <1> 	;;OUT	INTB01,AL
  5512                              <1> 	;;IODELAY
  5513                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5514                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5515                              <1> 	;;;JMP	$+2
  5516                              <1> 	;;IODELAY
  5517                              <1> 	;;OUT	INTA01,AL
  5518                              <1> 	;
  5519                              <1> 	;STI
  5520                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5521                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5522                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5523                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5524                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5525                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5526                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5527                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5528                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5529                              <1> 	;mov	si, hd0_type
  5530 00002750 BE[E0660000]        <1> 	mov	esi, hd0_type
  5531                              <1> 	;mov	cx, 4
  5532 00002755 B904000000          <1> 	mov	ecx, 4
  5533                              <1> hde_l:
  5534 0000275A AC                  <1> 	lodsb
  5535 0000275B 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5536 0000275D 7206                <1> 	jb	short _L4
  5537 0000275F FE05[C06C0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5538                              <1> _L4: ; 26/02/2015
  5539 00002765 E2F3                <1> 	loop	hde_l	
  5540                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5541                              <1> ;L4:
  5542                              <1> 	; 
  5543                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5544                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5545                              <1> 	;;mov 	cl, 3
  5546                              <1> 	;;
  5547                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5548                              <1> ;;hdc_dl:
  5549                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5550                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5551                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5552                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5553                              <1> 	;;jnc	short hdc_reset0
  5554                              <1> 	;;loop	hdc_dl
  5555                              <1> 	;;; 27/12/2014
  5556                              <1> 	;;stc
  5557                              <1> 	;;retn
  5558                              <1> 	;
  5559                              <1> ;;hdc_reset0:
  5560                              <1> 	; 18/01/2015
  5561 00002767 8A0D[C06C0000]      <1> 	mov	cl, [HF_NUM]
  5562 0000276D 20C9                <1> 	and	cl, cl
  5563 0000276F 740D                <1> 	jz	short POD_DONE
  5564                              <1> 	;
  5565 00002771 B27F                <1> 	mov	dl, 7Fh
  5566                              <1> hdc_reset1:
  5567 00002773 FEC2                <1> 	inc	dl
  5568                              <1> 	;; 31/12/2015
  5569                              <1> 	;;push	dx
  5570                              <1> 	;;push	cx
  5571                              <1> 	;;push	ds
  5572                              <1> 	;;sub	ax, ax
  5573                              <1> 	;;mov	ds, ax
  5574                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5575                              <1> 	;;pop	ds
  5576                              <1> 	;;MOV	BX,AX
  5577                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5578                              <1> 	;;MOV	CX,AX
  5579                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5580                              <1> 	;;
  5581                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5582                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5583                              <1> 	;;pop	cx
  5584                              <1> 	;;pop	dx
  5585                              <1> 	;;
  5586                              <1> 	; 18/01/2015
  5587 00002775 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5588                              <1> 	;int	13h
  5589 00002777 E8A3FFFFFF          <1> 	call	int13h
  5590 0000277C E2F5                <1> 	loop	hdc_reset1
  5591                              <1> POD_DONE:
  5592 0000277E C3                  <1> 	RETn
  5593                              <1> 
  5594                              <1> ;;-----	POD_ERROR
  5595                              <1> 
  5596                              <1> ;;CTL_ERRX:
  5597                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5598                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5599                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5600                              <1> ;	;JMP	short POD_DONE
  5601                              <1> 
  5602                              <1> ;;HD_RESET_1:
  5603                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5604                              <1> ;;	;PUSH	CX
  5605                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5606                              <1> ;;	INT	13H
  5607                              <1> ;;	JC	short RES_2
  5608                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5609                              <1> ;;	INT	13H
  5610                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5611                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5612                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5613                              <1> ;;					; (30 seconds)		
  5614                              <1> ;;	;cmc
  5615                              <1> ;;	;JNC	short RES_1
  5616                              <1> ;;	jb	short RES_1
  5617                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5618                              <1> ;;	;TEST	DL,1
  5619                              <1> ;;	;JNZ	RES_E1
  5620                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5621                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5622                              <1> ;;	;JMP	SHORT RES_E1
  5623                              <1> ;;RES_ER: ; 22/12/2014
  5624                              <1> ;;RES_OK:
  5625                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5626                              <1> ;;	;POP	BX
  5627                              <1> ;;	RETn
  5628                              <1> ;;
  5629                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5630                              <1> ;;	INT	13H
  5631                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5632                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5633                              <1> ;;	INT	13H
  5634                              <1> ;;	JC	short RES_ER
  5635                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5636                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5637                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5638                              <1> ;;	INT	13H
  5639                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5640                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5641                              <1> ;;	JE	short RES_OK
  5642                              <1> ;;	CMP	AH,DATA_CORRECTED
  5643                              <1> ;;	JE	short RES_OK
  5644                              <1> ;;	CMP	AH,BAD_ECC
  5645                              <1> ;;	JE	short RES_OK
  5646                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5647                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5648                              <1> ;;					; (60 seconds)		
  5649                              <1> ;;	cmc
  5650                              <1> ;;	JC	short RES_ER		; FAILED
  5651                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5652                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5653                              <1> ;;	AND	AL,3FH
  5654                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5655                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5656                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5657                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5658                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5659                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5660                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5661                              <1> ;;	;TEST	DL,1
  5662                              <1> ;;	;JNZ	short RES_E1
  5663                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5664                              <1> ;;;RES_E1:
  5665                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5666                              <1> ;;;RES_OK:
  5667                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5668                              <1> ;;	;POP	BX
  5669                              <1> ;;	;RETn
  5670                              <1> ;
  5671                              <1> ;;SET_FAIL:
  5672                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5673                              <1> ;	;CALL	CMOS_READ
  5674                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5675                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5676                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5677                              <1> ;	;RETn
  5678                              <1> ;
  5679                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5680                              <1> ;	;POP	AX			; SAVE RETURN
  5681                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5682                              <1> ;	;POP	BX
  5683                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5684                              <1> ;	;PUSH	CX
  5685                              <1> ;	;PUSH	AX
  5686                              <1> ;	;push	ds
  5687                              <1> ;	;xor	ax, ax
  5688                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5689                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5690                              <1> ;	;				; BX = START TIME
  5691                              <1> ;	;				; CX = END TIME
  5692                              <1> ;	;pop	ds
  5693                              <1> ;	;CMP	BX,CX
  5694                              <1> ;	;JB	short TCHK1		; START < END
  5695                              <1> ;	;CMP	BX,AX
  5696                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5697                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5698                              <1> ;;TCHK1: CMP	AX,BX
  5699                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5700                              <1> ;;TCHK2: CMP	AX,CX
  5701                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5702                              <1> ;;					; OR CURRENT < END < START
  5703                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5704                              <1> ;;	RETn
  5705                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5706                              <1> ;;	RETn
  5707                              <1> ;;
  5708                              <1> ;;int_13h:
  5709                              <1> 
  5710                              <1> ;----------------------------------------
  5711                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5712                              <1> ;----------------------------------------
  5713                              <1> 
  5714                              <1> DISK_IO:
  5715 0000277F 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5716                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5717                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5718                              <1> 	;;call	int40h
  5719                              <1> 	;jb	DISKETTE_IO_1
  5720                              <1> 	; 24/12/2021
  5721 00002782 7305                <1> 	jnb	short A1
  5722 00002784 E95FF1FFFF          <1> 	jmp	DISKETTE_IO_1
  5723                              <1> ;RET_2:
  5724                              <1> 	;RETf	2			; BACK TO CALLER
  5725                              <1> ;	retf	4
  5726                              <1> A1:
  5727 00002789 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5728                              <1> 	;; 04/01/2015
  5729                              <1> 	;;OR	AH,AH
  5730                              <1> 	;;JNZ	short A2
  5731                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5732                              <1> 	;;SUB	AH,AH
  5733 0000278A 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5734 0000278D 772E                <1> 	JA	short RET_2
  5735                              <1> 	; 18/01/2015
  5736 0000278F 08E4                <1> 	or	ah,ah
  5737 00002791 742D                <1> 	jz	short A4
  5738 00002793 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5739 00002796 7504                <1> 	jne	short A2
  5740 00002798 28E4                <1> 	sub	ah,ah	; Reset
  5741 0000279A EB24                <1> 	jmp	short A4
  5742                              <1> A2:
  5743 0000279C 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5744                              <1> 	;JNZ	short A3
  5745                              <1>         ;JMP    GET_PARM_N
  5746                              <1> 	;je	GET_PARM_N
  5747                              <1> 	; 24/12/2021
  5748 0000279F 7505                <1> 	jne	short A3
  5749 000027A1 E90D030000          <1> 	jmp	GET_PARM_N
  5750                              <1> A3:	
  5751 000027A6 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5752                              <1> 	;JNZ	short A4
  5753                              <1>         ;JMP    READ_DASD_TYPE
  5754                              <1> 	;je	READ_DASD_TYPE
  5755                              <1> 	; 24/12/2021
  5756 000027A9 7505                <1> 	jne	short A3_A4
  5757 000027AB E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5758                              <1> A3_A4:
  5759                              <1> 	; 02/02/2015
  5760 000027B0 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5761                              <1> 	; 12/01/2015
  5762 000027B3 F5                  <1> 	cmc
  5763 000027B4 730A                <1> 	jnc	short A4
  5764                              <1> 	; 30/01/2015
  5765                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5766 000027B6 C605[BF6C0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5767                              <1> 	;jmp	short RET_2
  5768                              <1> RET_2:
  5769 000027BD CA0400              <1> 	retf	4
  5770                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5771 000027C0 C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5772 000027C4 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5773 000027C5 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5774 000027C6 52                  <1> 	PUSH	eDX
  5775 000027C7 1E                  <1> 	PUSH	DS
  5776 000027C8 06                  <1> 	PUSH	ES
  5777 000027C9 56                  <1> 	PUSH	eSI
  5778 000027CA 57                  <1> 	PUSH	eDI
  5779                              <1> 	;;04/01/2015
  5780                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5781                              <1> 	;;JNZ	short A5
  5782                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5783                              <1> ;;A5:	
  5784                              <1> 	;push	cs
  5785                              <1> 	;pop	ds
  5786                              <1> 	; 21/02/2015
  5787                              <1> 	;push	ax
  5788                              <1> 	; 24/12/2021
  5789 000027CB 50                  <1> 	push	eax
  5790 000027CC 66B81000            <1> 	mov	ax, KDATA
  5791 000027D0 8ED8                <1> 	mov	ds, ax
  5792 000027D2 8EC0                <1> 	mov	es, ax	
  5793                              <1> 	;pop	ax
  5794                              <1> 	; 24/12/2021
  5795 000027D4 58                  <1> 	pop	eax
  5796 000027D5 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5797                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5798 000027DA 8A25[BF6C0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5799 000027E0 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5800 000027E3 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5801 000027E4 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5802 000027E5 5E                  <1> 	POP	eSI
  5803 000027E6 07                  <1>         POP     ES
  5804 000027E7 1F                  <1>         POP     DS
  5805 000027E8 5A                  <1> 	POP	eDX
  5806 000027E9 59                  <1> 	POP	eCX
  5807 000027EA 5B                  <1> 	POP	eBX
  5808 000027EB C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5809                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5810 000027EC CA0400              <1> 	retf	4
  5811                              <1> ; 21/02/2015
  5812                              <1> ;       dw --> dd
  5813                              <1> M1:					; FUNCTION TRANSFER TABLE
  5814 000027EF [A8290000]          <1> 	dd	DISK_RESET		; 000H
  5815 000027F3 [1D2A0000]          <1> 	dd	RETURN_STATUS		; 001H
  5816 000027F7 [2A2A0000]          <1> 	dd	DISK_READ		; 002H
  5817 000027FB [332A0000]          <1> 	dd	DISK_WRITE		; 003H
  5818 000027FF [3C2A0000]          <1> 	dd	DISK_VERF		; 004H
  5819 00002803 [542A0000]          <1> 	dd	FMT_TRK 		; 005H
  5820 00002807 [9E290000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5821 0000280B [9E290000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5822 0000280F [9E290000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5823 00002813 [152B0000]          <1> 	dd	INIT_DRV		; 009H
  5824 00002817 [742B0000]          <1> 	dd	RD_LONG 		; 00AH
  5825 0000281B [7D2B0000]          <1> 	dd	WR_LONG 		; 00BH
  5826 0000281F [862B0000]          <1> 	dd	DISK_SEEK		; 00CH
  5827 00002823 [A8290000]          <1> 	dd	DISK_RESET		; 00DH
  5828 00002827 [9E290000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5829 0000282B [9E290000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5830 0000282F [AE2B0000]          <1> 	dd	TST_RDY 		; 010H
  5831 00002833 [D22B0000]          <1> 	dd	HDISK_RECAL		; 011H
  5832 00002837 [9E290000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5833 0000283B [9E290000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5834 0000283F [082C0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5835                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5836 00002843 [9E290000]          <1> 	dd	BAD_COMMAND		; 015h
  5837 00002847 [9E290000]          <1> 	dd	BAD_COMMAND		; 016h
  5838 0000284B [9E290000]          <1> 	dd	BAD_COMMAND		; 017h
  5839 0000284F [9E290000]          <1> 	dd	BAD_COMMAND		; 018h
  5840 00002853 [9E290000]          <1> 	dd	BAD_COMMAND		; 019h
  5841 00002857 [9E290000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5842 0000285B [2A2A0000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5843 0000285F [332A0000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5844                              <1> M1L     EQU    $-M1
  5845                              <1> 
  5846                              <1> DISK_IO_CONT:
  5847                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5848 00002863 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5849                              <1> 	;;JNZ	short SU0
  5850                              <1>         ;;JMP	RETURN_STATUS
  5851                              <1> 	;je	RETURN_STATUS
  5852                              <1> 	; 24/12/2021
  5853 00002866 7505                <1> 	jne	short SU0
  5854 00002868 E9B0010000          <1> 	jmp	RETURN_STATUS
  5855                              <1> SU0:
  5856 0000286D C605[BF6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5857                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5858                              <1> 	;mov	si, bx ;; 14/02/2015
  5859 00002874 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5860 00002876 8A1D[C06C0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5861                              <1> 	;; 04/01/2015
  5862                              <1> 	;;PUSH	AX
  5863 0000287C 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5864                              <1> 					; (get drive number as 0 to 3)
  5865 0000287F 38D3                <1> 	CMP	BL,DL
  5866                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5867                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5868                              <1> 	; 24/12/2021
  5869 00002881 7705                <1> 	ja	short su0_su1
  5870 00002883 E916010000          <1> 	jmp	BAD_COMMAND
  5871                              <1> su0_su1:
  5872                              <1>         ;;03/01/2015
  5873 00002888 29DB                <1> 	sub	ebx, ebx
  5874 0000288A 88D3                <1> 	mov	bl, dl
  5875                              <1> 	;sub	bh, bh
  5876 0000288C 883D[D46C0000]      <1> 	mov	[LBAMode], bh 	; 0
  5877                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5878                              <1> 	;test	byte [ebx+hd0_type], 1
  5879                              <1> 	;jz	short su1		; no
  5880                              <1> 	;inc	byte [LBAMode]
  5881                              <1> ;su1:
  5882                              <1> 	; 21/02/2015 (32 bit modification)
  5883                              <1> 	; 04/01/2015
  5884                              <1> 	;push	ax ; ***
  5885                              <1> 	; 24/12/2021
  5886 00002892 50                  <1> 	push	eax ; ***
  5887                              <1> 	;PUSH	ES ; **
  5888                              <1> 	;PUSH	DX ; *
  5889                              <1> 	; 24/12/2021
  5890 00002893 52                  <1> 	push	edx ; *
  5891                              <1> 	;push	ax
  5892 00002894 50                  <1> 	push	eax
  5893 00002895 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5894                              <1> 	; 02/02/2015
  5895                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5896 0000289A 668B4310            <1> 	mov	ax, [ebx+16]
  5897 0000289E 66A3[D4660000]      <1> 	mov	[HF_PORT], ax
  5898                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5899 000028A4 668B5312            <1> 	mov	dx, [ebx+18]
  5900 000028A8 668915[D6660000]    <1> 	mov	[HF_REG_PORT], dx
  5901                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5902 000028AF 8A4314              <1> 	mov	al, [ebx+20]
  5903                              <1> 	; 23/02/2015
  5904 000028B2 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5905 000028B4 7406                <1> 	jz 	short su1
  5906 000028B6 FE05[D46C0000]      <1> 	inc	byte [LBAMode] ; 1 
  5907                              <1> su1: 	 
  5908 000028BC C0E804              <1> 	shr 	al, 4
  5909 000028BF 2401                <1> 	and	al, 1			
  5910 000028C1 A2[D8660000]        <1> 	mov	[hf_m_s], al 
  5911                              <1> 	;
  5912                              <1> 	; 03/01/2015
  5913                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  5914 000028C6 8A4308              <1> 	mov	al, [ebx+8]
  5915                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  5916 000028C9 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  5917                              <1> 					; Control Byte:  (= 08h, here)
  5918                              <1> 					; bit 0 - 0
  5919                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5920                              <1> 					; bit 2 - SRST (software RESET)
  5921                              <1> 					; bit 3 - use extra heads (8 to 15)
  5922                              <1> 					;         -always set to 1-	
  5923                              <1> 					; (bits 3 to 7 are reserved
  5924                              <1> 					;          for ATA devices)
  5925 000028CA 8A25[C16C0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5926 000028D0 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  5927 000028D3 08C4                <1> 	OR	AH,AL
  5928 000028D5 8825[C16C0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  5929                              <1> 	; 04/01/2015
  5930                              <1> 	;pop	ax
  5931                              <1> 	; 24/12/2021
  5932 000028DB 58                  <1> 	pop	eax
  5933                              <1> 	;pop	dx ; * ;; 14/02/2015
  5934                              <1> 	; 24/12/2021
  5935 000028DC 5A                  <1> 	pop	edx ; *
  5936 000028DD 20E4                <1> 	and	ah, ah	; Reset function ?
  5937 000028DF 7506                <1> 	jnz	short su2
  5938                              <1> 	;;pop	dx ; * ;; 14/02/2015
  5939                              <1> 	;pop	es ; **
  5940                              <1> 	;pop	ax ; ***
  5941                              <1> 	; 24/12/2021
  5942 000028E1 58                  <1> 	pop	eax ; ***	
  5943                              <1> 	;;pop	bx
  5944 000028E2 E9C1000000          <1>         jmp     DISK_RESET
  5945                              <1> su2:
  5946 000028E7 803D[D46C0000]00    <1> 	cmp	byte [LBAMode], 0
  5947 000028EE 765E                <1> 	jna	short su3
  5948                              <1> 	;
  5949                              <1> 	; 02/02/2015 (LBA read/write function calls)
  5950 000028F0 80FC1B              <1> 	cmp	ah, 1Bh
  5951 000028F3 720B                <1> 	jb	short lbarw1
  5952 000028F5 80FC1C              <1> 	cmp	ah, 1Ch
  5953 000028F8 7759                <1> 	ja 	short invldfnc
  5954                              <1> 	;;pop	dx ; * ; 14/02/2015
  5955                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5956 000028FA 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5957                              <1> 	;; 14/02/2015
  5958 000028FC 88D1                <1> 	mov	cl, dl ; 14/02/2015
  5959                              <1> 	;;mov	dx, bx
  5960                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5961                              <1> 	;;mov	bx, di
  5962                              <1> 	;mov	si, di ; Buffer offset
  5963 000028FE EB2E                <1> 	jmp	short lbarw2
  5964                              <1> lbarw1:
  5965                              <1> 	; convert CHS to LBA
  5966                              <1> 	;
  5967                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5968                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5969                              <1> 	;	+ Sector - 1
  5970                              <1> 	;push	dx ; * ;; 14/02/2015
  5971                              <1> 	; 24/12/2021
  5972 00002900 52                  <1> 	push	edx ; *
  5973                              <1> 	;xor	dh, dh
  5974 00002901 31D2                <1> 	xor	edx, edx
  5975                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  5976 00002903 8A530E              <1> 	mov	dl, [ebx+14]
  5977                              <1> 	;xor	ah, ah
  5978 00002906 31C0                <1> 	xor	eax, eax
  5979                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  5980 00002908 8A4302              <1> 	mov	al, [ebx+2]
  5981 0000290B FEC8                <1> 	dec	al
  5982                              <1> 	;inc	ax		; 0 =  256
  5983 0000290D 40                  <1> 	inc	eax ; 24/12/2021
  5984 0000290E 66F7E2              <1> 	mul 	dx
  5985                              <1> 		; AX = # of Heads" * Sectors/Track
  5986 00002911 6689CA              <1> 	mov	dx, cx
  5987                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  5988 00002914 83E13F              <1> 	and	ecx, 3fh
  5989 00002917 86D6                <1> 	xchg	dl, dh
  5990 00002919 C0EE06              <1> 	shr	dh, 6
  5991                              <1> 		; DX = cylinder (0 to 1023)
  5992                              <1> 	;mul 	dx
  5993                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  5994 0000291C F7E2                <1> 	mul	edx
  5995 0000291E FEC9                <1> 	dec	cl  ; sector - 1
  5996                              <1> 	;add	ax, cx
  5997                              <1> 	;adc	dx, 0
  5998                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  5999 00002920 01C8                <1> 	add	eax, ecx
  6000                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6001                              <1> 	; 24/12/2021
  6002 00002922 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6003                              <1> 	;push	dx
  6004                              <1> 	;push	ax
  6005 00002923 50                  <1> 	push	eax
  6006                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6007 00002924 8A430E              <1> 	mov	al, [ebx+14]
  6008 00002927 F6E5                <1> 	mul	ch
  6009                              <1> 		; AX = Head * Sectors/Track
  6010 00002929 6699                <1>         cwd
  6011                              <1> 	;pop	dx
  6012 0000292B 5A                  <1> 	pop	edx
  6013                              <1> 	;add	ax, dx
  6014                              <1> 	;pop	dx
  6015                              <1> 	;adc	dx, 0 ; add carry bit
  6016 0000292C 01D0                <1> 	add	eax, edx
  6017                              <1> lbarw2:
  6018 0000292E 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6019 00002930 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6020 00002932 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6021                              <1> 				; NOTE: Features register (1F1h, 171h)
  6022                              <1> 				; is not used for ATA device R/W functions. 
  6023                              <1> 				; It is old/obsolete 'write precompensation'
  6024                              <1> 				; register and error register
  6025                              <1> 				; for old ATA/IDE devices.
  6026                              <1> 	; 18/01/2014
  6027                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6028 00002936 8A0D[D8660000]      <1> 	mov	cl, [hf_m_s]
  6029                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6030                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6031                              <1> 				; bit 6 = 1 = LBA mode
  6032                              <1> 				; bit 7 = 1
  6033 0000293C 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6034                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6035 0000293F 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6036 00002944 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6037                              <1> 	;or	dh, ch
  6038 00002947 09C8                <1> 	or	eax, ecx	
  6039                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6040                              <1> 				  ; (Sector Number Register)
  6041                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6042                              <1> 				  ; (Cylinder Low Register)
  6043                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6044                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6045                              <1> 				  ; (Cylinder High Register)
  6046                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6047                              <1> 				  ; (Drive/Head Register)
  6048                              <1> 	
  6049                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6050 00002949 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6051                              <1> 	;14/02/2015
  6052                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6053 0000294C EB37                <1> 	jmp	short su4
  6054                              <1> su3:
  6055                              <1> 	; 02/02/2015 
  6056                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6057 0000294E 80FC14              <1> 	cmp 	ah, 14h
  6058 00002951 7603                <1> 	jna 	short chsfnc
  6059                              <1> invldfnc:
  6060                              <1>         ; 14/02/2015  
  6061                              <1> 	;pop	es ; **
  6062                              <1>         ;pop	ax ; ***
  6063                              <1>         ; 24/12/2021
  6064 00002953 58                  <1> 	pop	eax ; ***
  6065                              <1> 	;jmp	short BAD_COMMAND_POP
  6066 00002954 EB48                <1>         jmp     short BAD_COMMAND
  6067                              <1> chsfnc:	
  6068                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6069 00002956 668B4305            <1> 	mov	ax, [ebx+5]
  6070 0000295A 66C1E802            <1> 	SHR	AX,2
  6071 0000295E 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6072                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6073                              <1> 	;;PUSH	DX
  6074                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6075                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6076                              <1> 	;;POP	DX ; * 
  6077                              <1> 	;;POP	ES ; **
  6078                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6079                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6080                              <1> 	;;OR	AH,AL
  6081                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6082                              <1> 	;
  6083 00002961 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6084 00002963 243F                <1> 	AND	AL,3FH
  6085 00002965 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6086 00002968 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6087 0000296B 88C8                <1> 	MOV	AL,CL
  6088 0000296D C0E806              <1> 	SHR	AL,6
  6089 00002970 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6090                              <1> 	;;05/01/2015
  6091                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6092 00002973 A0[D8660000]        <1> 	mov	al, [hf_m_s]
  6093 00002978 C0E004              <1> 	SHL	AL,4
  6094 0000297B 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6095 0000297E 08F0                <1> 	OR	AL,DH
  6096                              <1> 	;OR	AL,80H or 20H
  6097 00002980 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6098 00002982 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6099                              <1> su4:
  6100                              <1> 	;POP	ES ; **
  6101                              <1>         ;; 14/02/2015
  6102                              <1>         ;;POP   AX
  6103                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6104                              <1>         ;;PUSH  AX
  6105                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6106                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6107                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6108                              <1> 	;pop     ax ; ***
  6109                              <1> 	; 24/12/2021
  6110 00002985 58                  <1> 	pop	eax ; ***
  6111 00002986 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6112 00002989 29DB                <1>         sub	ebx, ebx
  6113 0000298B 88E3                <1> 	mov     bl, ah
  6114                              <1>         ;xor	bh, bh
  6115                              <1>         ;sal	bx, 1
  6116 0000298D 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6117                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6118                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6119                              <1>         ;;JNB   short BAD_COMMAND_POP
  6120                              <1>         ;cmp	bx, M1L
  6121 00002991 83FB74              <1> 	cmp	ebx, M1L
  6122 00002994 7308                <1> 	jnb	short BAD_COMMAND
  6123                              <1>         ;xchg	bx, si
  6124 00002996 87DE                <1>         xchg	ebx, esi
  6125                              <1> 	;;;POP	AX			; RESTORE AX
  6126                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6127                              <1> 	
  6128                              <1> 	;;PUSH	CX
  6129                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6130                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6131                              <1> 	;SHR	CX,4
  6132                              <1> 	;MOV	AX,ES
  6133                              <1> 	;ADD	AX,CX
  6134                              <1> 	;MOV	ES,AX
  6135                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6136                              <1> 	;;POP	AX
  6137                              <1> 	;;POP	CX
  6138                              <1> 	;;JMP	word [CS:SI+M1]
  6139                              <1> 	;jmp	word [SI+M1]
  6140 00002998 FFA6[EF270000]      <1> 	jmp	dword [esi+M1]
  6141                              <1> ;;BAD_COMMAND_POP:
  6142                              <1> ;;	POP	AX
  6143                              <1> ;;	POP	BX
  6144                              <1> BAD_COMMAND:
  6145 0000299E C605[BF6C0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6146 000029A5 B000                <1> 	MOV	AL,0
  6147 000029A7 C3                  <1> 	RETn
  6148                              <1> 
  6149                              <1> ;----------------------------------------
  6150                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6151                              <1> ;----------------------------------------
  6152                              <1> 
  6153                              <1> ; 18-1-2015 : one controller reset (not other one)
  6154                              <1> 
  6155                              <1> DISK_RESET:
  6156 000029A8 FA                  <1> 	CLI
  6157 000029A9 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6158                              <1> 	;JMP	$+2
  6159                              <1> 	IODELAY
  2046 000029AB EB00                <2>  jmp short $+2
  2047 000029AD EB00                <2>  jmp short $+2
  6160                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6161 000029AF 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6162 000029B1 E6A1                <1> 	OUT	INTB01,AL
  6163 000029B3 FB                  <1> 	STI				; START INTERRUPTS
  6164                              <1> 	; 14/02/2015
  6165                              <1> 	;mov	di, dx
  6166                              <1> 	; 24/12/2021
  6167 000029B4 89D7                <1> 	mov	edi, edx	
  6168                              <1> 	; 04/01/2015
  6169                              <1> 	;xor	di,di
  6170                              <1> drst0:
  6171 000029B6 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6172                              <1> 	;MOV	DX,HF_REG_PORT
  6173 000029B8 668B15[D6660000]    <1> 	MOV	DX,[HF_REG_PORT]
  6174 000029BF EE                  <1> 	OUT	DX,AL			; RESET
  6175                              <1> ;	MOV	CX,10			; DELAY COUNT
  6176                              <1> ;DRD:	DEC	CX
  6177                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6178                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6179 000029C0 B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6180 000029C5 E8CDEBFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6181                              <1>                                         ; 40 micro seconds)
  6182 000029CA A0[C16C0000]        <1> 	mov	al,[CONTROL_BYTE]
  6183 000029CF 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6184 000029D1 EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6185 000029D2 E807040000          <1> 	CALL	NOT_BUSY
  6186 000029D7 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6187 000029D9 668B15[D4660000]    <1> 	MOV	DX,[HF_PORT]
  6188 000029E0 FEC2                <1> 	inc	dl  ; HF_PORT+1
  6189                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6190                              <1>         ;mov	cl, 10
  6191 000029E2 B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6192                              <1> drst1:
  6193 000029E7 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6194 000029E8 3C01                <1> 	CMP	AL,1
  6195                              <1> 	; 04/01/2015
  6196 000029EA 740A                <1> 	jz	short drst2
  6197                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6198                              <1>         	; Drive/Head Register - bit 4
  6199 000029EC E2F9                <1> 	loop	drst1
  6200                              <1> DRERR:	
  6201 000029EE C605[BF6C0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6202 000029F5 C3                  <1> 	RETn
  6203                              <1> drst2:
  6204                              <1> 	; 14/02/2015
  6205                              <1> 	;mov	dx, di
  6206                              <1> 	; 24/12/2021
  6207 000029F6 89FA                <1> 	mov	edx, edi
  6208                              <1> ;drst3:
  6209                              <1> ;	; 05/01/2015
  6210                              <1> ;	shl 	di,1
  6211                              <1> ;	; 04/01/2015
  6212                              <1> ;	mov	ax,[di+hd_cports]
  6213                              <1> ;	cmp	ax,[HF_REG_PORT]
  6214                              <1> ;	je	short drst4
  6215                              <1> ;	mov	[HF_REG_PORT], ax
  6216                              <1> ;	; 03/01/2015
  6217                              <1> ;	mov	ax,[di+hd_ports]
  6218                              <1> ;       mov     [HF_PORT], ax
  6219                              <1> ;	; 05/01/2014
  6220                              <1> ;	shr	di,1
  6221                              <1> ;	; 04/01/2015
  6222                              <1> ;	jmp	short drst0	; reset other controller
  6223                              <1> ;drst4:
  6224                              <1> ;	; 05/01/2015
  6225                              <1> ;	shr	di,1
  6226                              <1> ;	mov	al,[di+hd_dregs]
  6227                              <1> ;	and	al,10h ; bit 4 only
  6228                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6229                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6230                              <1> 	;
  6231 000029F8 A0[D8660000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6232 000029FD A801                <1> 	test	al,1
  6233                              <1> ;	jnz	short drst6
  6234 000029FF 7516                <1>         jnz     short drst4
  6235 00002A01 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6236                              <1> ;drst5:
  6237                              <1> drst3:
  6238 00002A05 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6239                              <1> 	;mov	dx,di
  6240 00002A0A E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6241                              <1> 	; 04/01/2014
  6242                              <1> ;	inc	di
  6243                              <1> ;	mov	dx,di
  6244                              <1> ;	cmp	dl,[HF_NUM]
  6245                              <1> ;	jb	short drst3
  6246                              <1> ;DRE:
  6247 00002A0F C605[BF6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6248 00002A16 C3                  <1> 	RETn
  6249                              <1> ;drst6:
  6250                              <1> drst4:		; Drive/Head Register - bit 4
  6251 00002A17 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6252                              <1>         ;jmp    short drst5
  6253 00002A1B EBE8                <1>         jmp     short drst3
  6254                              <1> 
  6255                              <1> ;----------------------------------------
  6256                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6257                              <1> ;----------------------------------------
  6258                              <1> 
  6259                              <1> RETURN_STATUS:
  6260 00002A1D A0[BF6C0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6261 00002A22 C605[BF6C0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6262 00002A29 C3                  <1> 	RETn
  6263                              <1> 
  6264                              <1> ;----------------------------------------
  6265                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6266                              <1> ;----------------------------------------
  6267                              <1> 
  6268                              <1> DISK_READ:
  6269 00002A2A C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6270 00002A2E E92A020000          <1>         JMP     COMMANDI
  6271                              <1> 
  6272                              <1> ;----------------------------------------
  6273                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6274                              <1> ;----------------------------------------
  6275                              <1> 
  6276                              <1> DISK_WRITE:
  6277 00002A33 C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6278 00002A37 E976020000          <1>         JMP     COMMANDO
  6279                              <1> 
  6280                              <1> ;----------------------------------------
  6281                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6282                              <1> ;----------------------------------------
  6283                              <1> 
  6284                              <1> DISK_VERF:
  6285 00002A3C C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6286 00002A40 E8E4020000          <1> 	CALL	COMMAND
  6287 00002A45 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6288 00002A47 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6289 00002A4C 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6290 00002A4E E8E3030000          <1> 	CALL	CHECK_STATUS
  6291                              <1> VERF_EXIT:
  6292 00002A53 C3                  <1> 	RETn
  6293                              <1> 
  6294                              <1> ;----------------------------------------
  6295                              <1> ;	FORMATTING	     (AH = 05H) :
  6296                              <1> ;----------------------------------------
  6297                              <1> 
  6298                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6299 00002A54 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6300                              <1> 	;PUSH	ES
  6301                              <1> 	;PUSH	BX
  6302 00002A58 53                  <1> 	push	ebx
  6303 00002A59 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6304                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6305 00002A5E 8A430E              <1> 	mov	al, [ebx+14]
  6306 00002A61 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6307 00002A64 5B                  <1> 	pop	ebx
  6308                              <1> 	;POP	BX
  6309                              <1> 	;POP	ES
  6310 00002A65 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6311                              <1> 
  6312                              <1> ;----------------------------------------
  6313                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6314                              <1> ;----------------------------------------
  6315                              <1> 
  6316                              <1> READ_DASD_TYPE:
  6317                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6318 00002A6A 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6319                              <1> 	;PUSH	ES
  6320 00002A6B 53                  <1> 	PUSH	eBX
  6321                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6322                              <1> 	;push	cs
  6323                              <1> 	;pop	ds
  6324 00002A6C 66BB1000            <1>         mov	bx, KDATA
  6325 00002A70 8EDB                <1> 	mov	ds, bx
  6326                              <1> 	;mov	es, bx
  6327 00002A72 C605[BF6C0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6328 00002A79 8A1D[C06C0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6329 00002A7F 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6330 00002A82 38D3                <1> 	CMP	BL,DL
  6331 00002A84 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6332 00002A86 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6333                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6334 00002A8B 8A4302              <1> 	mov	al, [ebx+2]
  6335                              <1> 	;MOV	CL,[ES:BX+14]
  6336 00002A8E 8A4B0E              <1> 	mov	cl, [ebx+14]
  6337 00002A91 F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6338                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6339 00002A93 668B0B              <1> 	mov	cx, [ebx]
  6340                              <1> 	;
  6341                              <1> 	; 02/01/2015 
  6342                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6343                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6344 00002A96 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6345                              <1> 	;
  6346 00002A98 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6347 00002A9B 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6348 00002A9E 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6349                              <1> 	;SUB	AX,AX
  6350 00002AA1 28C0                <1> 	sub	al, al
  6351 00002AA3 B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6352 00002AA5 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6353                              <1> 	;POP	ES
  6354 00002AA6 1F                  <1> 	POP	DS
  6355 00002AA7 F8                  <1> 	CLC				; CLEAR CARRY
  6356                              <1> 	;RETf	2
  6357 00002AA8 CA0400              <1> 	retf	4
  6358                              <1> RDT_NOT_PRESENT:
  6359                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6360                              <1> 	; 24/12/2021
  6361 00002AAB 29C0                <1> 	sub	eax, eax
  6362                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6363                              <1> 	;MOV	DX,AX
  6364 00002AAD 89C1                <1> 	mov	ecx, eax
  6365 00002AAF 89C2                <1> 	mov	edx, eax
  6366 00002AB1 EBF2                <1> 	JMP	short RDT2
  6367                              <1> 
  6368                              <1> ;----------------------------------------
  6369                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6370                              <1> ;----------------------------------------
  6371                              <1> 
  6372                              <1> GET_PARM_N:
  6373                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6374 00002AB3 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6375                              <1> 	;PUSH	ES
  6376 00002AB4 53                  <1> 	PUSH	eBX
  6377                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6378                              <1> 	;MOV	DS,AX
  6379                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6380                              <1> 	;JZ	short G0
  6381                              <1> 	;LES	BX,@HF1_TBL_VEC
  6382                              <1> 	;JMP	SHORT G1
  6383                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6384                              <1> ;G1:
  6385                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6386                              <1> 	; 22/12/2014
  6387                              <1> 	;push	cs
  6388                              <1> 	;pop	ds
  6389 00002AB5 66BB1000            <1> 	mov	bx, KDATA
  6390 00002AB9 8EDB                <1> 	mov	ds, bx
  6391                              <1> 	;mov	es, bx
  6392                              <1> 	;
  6393 00002ABB 80EA80              <1> 	SUB	DL,80H
  6394 00002ABE 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6395 00002AC1 7340                <1> 	JAE	short G4
  6396                              <1> 	;
  6397 00002AC3 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6398                              <1> 	; 22/12/2014
  6399 00002AC5 88D3                <1> 	mov	bl, dl
  6400                              <1> 	;xor	bh, bh  
  6401 00002AC7 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6402                              <1> 	;add	bx, HF_TBL_VEC
  6403 00002ACA 81C3[C46C0000]      <1> 	add	ebx, HF_TBL_VEC
  6404                              <1> 	;mov	ax, [bx+2]
  6405                              <1> 	;mov	es, ax			; dpt segment
  6406                              <1> 	;mov	bx, [bx]		; dpt offset
  6407 00002AD0 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6408                              <1> 
  6409 00002AD2 C605[BF6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6410                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6411 00002AD9 668B03              <1> 	mov	ax, [ebx]
  6412                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6413 00002ADC 6648                <1> 	dec	ax			; max. cylinder number
  6414 00002ADE 88C5                <1> 	MOV	CH,AL
  6415 00002AE0 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6416 00002AE4 66D1E8              <1> 	SHR	AX,1
  6417 00002AE7 66D1E8              <1> 	SHR	AX,1
  6418                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6419 00002AEA 0A430E              <1> 	or	al, [ebx+14]
  6420 00002AED 88C1                <1> 	MOV	CL,AL
  6421                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6422 00002AEF 8A7302              <1> 	mov	dh, [ebx+2]
  6423 00002AF2 FECE                <1> 	DEC	DH			; 0-N RANGE
  6424 00002AF4 8A15[C06C0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6425                              <1> 	;SUB	AX,AX
  6426                              <1> 	; 24/12/2021
  6427 00002AFA 29C0                <1> 	sub	eax, eax
  6428                              <1> 	; 27/12/2014 
  6429                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6430                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6431                              <1> 	;mov	di, bx			; HDPT offset
  6432 00002AFC 89DF                <1> 	mov	edi, ebx
  6433                              <1> G5:
  6434 00002AFE 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6435                              <1> 	;POP	ES
  6436 00002AFF 1F                  <1> 	POP	DS
  6437                              <1> 	;RETf	2
  6438 00002B00 CA0400              <1> 	retf	4
  6439                              <1> G4:
  6440 00002B03 C605[BF6C0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6441                              <1> 	; 24/12/2021
  6442 00002B0A 29C0                <1> 	sub	eax, eax
  6443 00002B0C B407                <1> 	MOV	AH,INIT_FAIL
  6444                              <1> 	;SUB	AL,AL
  6445                              <1> 	;SUB	DX,DX
  6446 00002B0E 29D2                <1> 	sub	edx, edx
  6447                              <1> 	;SUB	CX,CX
  6448 00002B10 29C9                <1> 	sub	ecx, ecx
  6449 00002B12 F9                  <1> 	STC				; SET ERROR FLAG
  6450 00002B13 EBE9                <1> 	JMP	short G5
  6451                              <1> 
  6452                              <1> ;----------------------------------------
  6453                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6454                              <1> ;----------------------------------------
  6455                              <1> 	; 03/01/2015
  6456                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6457                              <1> 	; logical sector per logical track
  6458                              <1> 	; and logical heads - 1 would be set but
  6459                              <1> 	; it is seen as it will be good
  6460                              <1> 	; if physical parameters will be set here
  6461                              <1> 	; because, number of heads <= 16.
  6462                              <1> 	; (logical heads usually more than 16)
  6463                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6464                              <1> 	;	== INT 13h physical parameters
  6465                              <1> 
  6466                              <1> ;INIT_DRV:
  6467                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6468                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6469                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6470                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6471                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6472                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6473                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6474                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6475                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6476                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6477                              <1> ;	SUB	AX,AX
  6478                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6479                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6480                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6481                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6482                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6483                              <1> ;	CALL	CHECK_STATUS
  6484                              <1> ;INIT_EXIT:
  6485                              <1> ;	RETn
  6486                              <1> 
  6487                              <1> ; 04/01/2015
  6488                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6489                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6490                              <1> INIT_DRV:
  6491                              <1> 	;xor	ah,ah
  6492 00002B15 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6493 00002B17 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6494 00002B19 3825[D46C0000]      <1>         cmp     [LBAMode], ah   ; 0
  6495 00002B1F 7702                <1> 	ja	short idrv0
  6496 00002B21 B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6497                              <1> idrv0:
  6498                              <1> 	; DL = drive number (0 based)
  6499 00002B23 E8BB030000          <1> 	call	GET_VEC
  6500                              <1> 	;push	bx
  6501 00002B28 53                  <1> 	push	ebx ; 21/02/2015
  6502                              <1> 	;add	bx,ax
  6503 00002B29 01C3                <1> 	add	ebx,eax
  6504                              <1> 	;; 05/01/2015
  6505 00002B2B 8A25[D8660000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6506                              <1> 	;;and 	ah,1 
  6507 00002B31 C0E404              <1> 	shl	ah,4
  6508 00002B34 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6509                              <1> 	;mov	al,[es:bx]
  6510 00002B37 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6511 00002B39 FEC8                <1> 	dec	al	 ; last head number 
  6512                              <1> 	;and	al,0Fh
  6513 00002B3B 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6514                              <1> 	;
  6515 00002B3D C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6516 00002B41 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6517                              <1> 	;pop	bx
  6518 00002B44 5B                  <1> 	pop	ebx
  6519 00002B45 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6520 00002B47 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6521 00002B49 803D[D46C0000]00    <1> 	cmp	byte [LBAMode],0
  6522 00002B50 7702                <1> 	ja	short idrv1
  6523 00002B52 B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6524                              <1> idrv1:
  6525                              <1> 	;xor	ah,ah
  6526                              <1> 	;add	bx,ax
  6527 00002B54 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6528                              <1> 	;mov	al,[es:bx]
  6529                              <1> 			; sector number
  6530 00002B56 8A03                <1> 	mov	al,[ebx]
  6531 00002B58 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6532 00002B5B 28C0                <1> 	sub	al,al
  6533 00002B5D 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6534 00002B60 E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6535 00002B65 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6536 00002B67 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6537 00002B6C 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6538 00002B6E E8C3020000          <1> 	call	CHECK_STATUS
  6539                              <1> INIT_EXIT:
  6540 00002B73 C3                  <1> 	RETn
  6541                              <1> 
  6542                              <1> ;----------------------------------------
  6543                              <1> ;	READ LONG	     (AH = 0AH) :
  6544                              <1> ;----------------------------------------
  6545                              <1> 
  6546                              <1> RD_LONG:
  6547                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6548 00002B74 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6549 00002B78 E9E0000000          <1>         JMP     COMMANDI
  6550                              <1> 
  6551                              <1> ;----------------------------------------
  6552                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6553                              <1> ;----------------------------------------
  6554                              <1> 
  6555                              <1> WR_LONG:
  6556                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6557 00002B7D C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6558 00002B81 E92C010000          <1>         JMP     COMMANDO
  6559                              <1> 
  6560                              <1> ;----------------------------------------
  6561                              <1> ;	SEEK		     (AH = 0CH) :
  6562                              <1> ;----------------------------------------
  6563                              <1> 
  6564                              <1> DISK_SEEK:
  6565 00002B86 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6566 00002B8A E89A010000          <1> 	CALL	COMMAND
  6567 00002B8F 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6568 00002B91 E80C020000          <1> 	CALL	_WAIT
  6569 00002B96 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6570 00002B98 E899020000          <1> 	CALL	CHECK_STATUS
  6571 00002B9D 803D[BF6C0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6572 00002BA4 7507                <1> 	JNE	short DS_EXIT
  6573 00002BA6 C605[BF6C0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6574                              <1> DS_EXIT:
  6575 00002BAD C3                  <1> 	RETn
  6576                              <1> 
  6577                              <1> ;----------------------------------------
  6578                              <1> ;	TEST DISK READY      (AH = 10H) :
  6579                              <1> ;----------------------------------------
  6580                              <1> 
  6581                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6582 00002BAE E82B020000          <1> 	CALL	NOT_BUSY
  6583 00002BB3 751C                <1> 	JNZ	short TR_EX
  6584 00002BB5 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6585 00002BB8 668B15[D4660000]    <1> 	MOV	DX,[HF_PORT]
  6586 00002BBF 80C206              <1> 	add	dl,6
  6587 00002BC2 EE                  <1> 	OUT	DX,AL
  6588 00002BC3 E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6589 00002BC8 7507                <1> 	JNZ	short TR_EX
  6590 00002BCA C605[BF6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6591                              <1> TR_EX:	
  6592 00002BD1 C3                  <1> 	RETn
  6593                              <1> 
  6594                              <1> ;----------------------------------------
  6595                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6596                              <1> ;----------------------------------------
  6597                              <1> 
  6598                              <1> HDISK_RECAL:
  6599 00002BD2 C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6600 00002BD6 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6601 00002BDB 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6602 00002BDD E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6603 00002BE2 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6604 00002BE4 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6605 00002BE9 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6606                              <1> RECAL_X:
  6607 00002BEB E846020000          <1> 	CALL	CHECK_STATUS
  6608 00002BF0 803D[BF6C0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6609 00002BF7 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6610 00002BF9 C605[BF6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6611                              <1> RECAL_EXIT:
  6612 00002C00 803D[BF6C0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6613 00002C07 C3                  <1> 	RETn
  6614                              <1> 
  6615                              <1> ;----------------------------------------
  6616                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6617                              <1> ;----------------------------------------
  6618                              <1> 
  6619                              <1> CTLR_DIAGNOSTIC:
  6620 00002C08 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6621 00002C09 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6622                              <1> 	;AND	AL,0BFH
  6623 00002C0B 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6624                              <1> 	;JMP	$+2
  6625                              <1> 	IODELAY
  2046 00002C0D EB00                <2>  jmp short $+2
  2047 00002C0F EB00                <2>  jmp short $+2
  6626 00002C11 E6A1                <1> 	OUT	INTB01,AL
  6627                              <1> 	IODELAY
  2046 00002C13 EB00                <2>  jmp short $+2
  2047 00002C15 EB00                <2>  jmp short $+2
  6628 00002C17 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6629 00002C19 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6630                              <1> 	;JMP	$+2
  6631                              <1> 	IODELAY
  2046 00002C1B EB00                <2>  jmp short $+2
  2047 00002C1D EB00                <2>  jmp short $+2
  6632 00002C1F E621                <1> 	OUT	INTA01,AL
  6633 00002C21 FB                  <1> 	STI
  6634 00002C22 E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6635 00002C27 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6636                              <1> 	;MOV	DX, HF_PORT+7
  6637 00002C29 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6638 00002C30 80C207              <1> 	add	dl, 7
  6639 00002C33 B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6640 00002C35 EE                  <1> 	OUT	DX,AL
  6641 00002C36 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6642 00002C3B B480                <1> 	MOV	AH,TIME_OUT
  6643 00002C3D 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6644                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6645 00002C3F 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6646 00002C46 FEC2                <1> 	inc	dl
  6647 00002C48 EC                  <1> 	IN	AL,DX
  6648 00002C49 A2[B66C0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6649 00002C4E B400                <1> 	MOV	AH,0
  6650 00002C50 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6651 00002C52 7402                <1> 	JE	SHORT CD_EXIT
  6652 00002C54 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6653                              <1> CD_EXIT:
  6654 00002C56 8825[BF6C0000]      <1> 	MOV	[DISK_STATUS1],AH
  6655 00002C5C C3                  <1> 	RETn
  6656                              <1> 
  6657                              <1> ;----------------------------------------
  6658                              <1> ; COMMANDI				:
  6659                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6660                              <1> ;	NSECTOR RETURNS ZERO		:
  6661                              <1> ;----------------------------------------
  6662                              <1> COMMANDI:
  6663 00002C5D E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6664 00002C62 724D                <1> 	JC	short CMD_ABORT
  6665                              <1> 	;MOV	DI,BX
  6666 00002C64 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6667 00002C66 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6668 00002C6B 7544                <1> 	JNZ	short CMD_ABORT
  6669                              <1> CMD_I1:
  6670 00002C6D E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6671 00002C72 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6672                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6673 00002C74 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6674                              <1> 	;MOV	DX,HF_PORT
  6675 00002C79 668B15[D4660000]    <1> 	mov	dx,[HF_PORT]
  6676 00002C80 FA                  <1> 	CLI
  6677 00002C81 FC                  <1> 	CLD
  6678 00002C82 F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6679 00002C85 FB                  <1> 	STI
  6680 00002C86 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6681 00002C8A 7419                <1> 	JZ	CMD_I3
  6682 00002C8C E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6683 00002C91 721E                <1> 	JC	short TM_OUT
  6684                              <1> 	;MOV	DX,HF_PORT
  6685 00002C93 668B15[D4660000]    <1> 	mov	dx,[HF_PORT]
  6686                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6687 00002C9A B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6688 00002C9F EC                  <1> CMD_I2: IN	AL,DX
  6689                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6690 00002CA0 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6691 00002CA2 47                  <1> 	INC	eDI
  6692 00002CA3 E2FA                <1> 	LOOP	CMD_I2
  6693 00002CA5 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6694 00002CAA 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6695 00002CAC FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6696 00002CAF 75BC                <1> 	JNZ	SHORT CMD_I1
  6697                              <1> CMD_ABORT:
  6698 00002CB1 C3                  <1> TM_OUT: RETn
  6699                              <1> 
  6700                              <1> ;----------------------------------------
  6701                              <1> ; COMMANDO				:
  6702                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6703                              <1> ;	NSECTOR RETURNS ZERO		:
  6704                              <1> ;----------------------------------------
  6705                              <1> COMMANDO:
  6706 00002CB2 E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6707 00002CB7 72F8                <1> 	JC	short CMD_ABORT
  6708 00002CB9 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6709 00002CBB E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6710 00002CC0 75EF                <1> 	JNZ	short CMD_ABORT
  6711 00002CC2 E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6712 00002CC7 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6713                              <1> CMD_O1: ;PUSH	DS
  6714                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6715                              <1> 	;POP	DS
  6716                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6717                              <1> 	;MOV	DX,HF_PORT
  6718                              <1> 	; 01/02/2015
  6719 00002CC9 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6720                              <1> 	;push	es
  6721                              <1> 	;pop	ds
  6722                              <1> 	;mov	cx, 256
  6723 00002CD0 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6724 00002CD5 FA                  <1> 	CLI
  6725 00002CD6 FC                  <1> 	CLD
  6726 00002CD7 F3666F              <1> 	REP	OUTSW
  6727 00002CDA FB                  <1> 	STI
  6728                              <1> 	;POP	DS			; RESTORE DS
  6729 00002CDB F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6730 00002CDF 7419                <1> 	JZ	short CMD_O3
  6731 00002CE1 E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6732 00002CE6 72C9                <1> 	JC	short TM_OUT
  6733                              <1> 	;MOV	DX,HF_PORT
  6734 00002CE8 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6735                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6736 00002CEF B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6737                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6738 00002CF4 8A06                <1> 	mov	al, [esi]
  6739 00002CF6 EE                  <1> 	OUT	DX,AL
  6740 00002CF7 46                  <1> 	INC	eSI
  6741 00002CF8 E2FA                <1> 	LOOP	CMD_O2
  6742                              <1> CMD_O3:
  6743 00002CFA E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6744 00002CFF 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6745 00002D01 E830010000          <1> 	CALL	CHECK_STATUS
  6746 00002D06 75A9                <1> 	JNZ	short CMD_ABORT
  6747 00002D08 F605[B56C0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6748 00002D0F 75B8                <1> 	JNZ	SHORT CMD_O1
  6749                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6750 00002D11 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6751                              <1> 	;add	dl, 2
  6752 00002D18 FEC2                <1> 	inc	dl
  6753 00002D1A FEC2                <1> 	inc	dl
  6754 00002D1C EC                  <1> 	IN	AL,DX			;
  6755 00002D1D A8FF                <1> 	TEST	AL,0FFH 		;
  6756 00002D1F 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6757 00002D21 C605[BF6C0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6758                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6759                              <1> CMD_O4:
  6760 00002D28 C3                  <1> 	RETn
  6761                              <1> 
  6762                              <1> ;--------------------------------------------------------
  6763                              <1> ; COMMAND						:
  6764                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6765                              <1> ; OUTPUT						:
  6766                              <1> ;	BL = STATUS					:
  6767                              <1> ;	BH = ERROR REGISTER				:
  6768                              <1> ;--------------------------------------------------------
  6769                              <1> 
  6770                              <1> COMMAND:
  6771 00002D29 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6772                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6773                              <1> COMMAND1:
  6774                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6775 00002D2A E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6776                              <1> 	;;POP	CX
  6777 00002D2F 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6778 00002D31 803D[BF6C0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6779                              <1> 	;JZ	short CMD_TIMEOUT
  6780                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6781                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6782 00002D38 7507                <1> 	jne	short COMMAND4
  6783                              <1> CMD_TIMEOUT:
  6784 00002D3A C605[BF6C0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6785                              <1> COMMAND4:
  6786 00002D41 5B                  <1> 	POP	eBX
  6787 00002D42 803D[BF6C0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6788 00002D49 C3                  <1> 	RETn
  6789                              <1> COMMAND2:
  6790 00002D4A 5B                  <1> 	POP	eBX
  6791 00002D4B 57                  <1> 	PUSH	eDI
  6792 00002D4C C605[B76C0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6793 00002D53 FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6794 00002D54 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6795                              <1> 	;AND	AL,0BFH
  6796 00002D56 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6797                              <1> 	;JMP	$+2
  6798                              <1> 	IODELAY
  2046 00002D58 EB00                <2>  jmp short $+2
  2047 00002D5A EB00                <2>  jmp short $+2
  6799 00002D5C E6A1                <1> 	OUT	INTB01,AL
  6800 00002D5E E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6801 00002D60 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6802                              <1> 	;JMP	$+2
  6803                              <1> 	IODELAY
  2046 00002D62 EB00                <2>  jmp short $+2
  2047 00002D64 EB00                <2>  jmp short $+2
  6804 00002D66 E621                <1> 	OUT	INTA01,AL
  6805 00002D68 FB                  <1> 	STI
  6806 00002D69 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6807                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6808 00002D6B 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6809 00002D72 FEC2                <1> 	inc	dl
  6810 00002D74 F605[C16C0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6811 00002D7B 7411                <1> 	JZ	short COMMAND3
  6812 00002D7D 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6813 00002D80 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6814 00002D82 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6815 00002D84 7208                <1> 	JB	short COMMAND3
  6816 00002D86 3C40                <1> 	CMP	AL,40H
  6817 00002D88 7704                <1> 	JA	short COMMAND3
  6818 00002D8A 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6819                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6820                              <1> COMMAND3:
  6821 00002D8E 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6822 00002D92 EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6823                              <1> 	IODELAY
  2046 00002D93 EB00                <2>  jmp short $+2
  2047 00002D95 EB00                <2>  jmp short $+2
  6824 00002D97 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6825 00002D98 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6826 00002D9A 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6827 00002D9E 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6828 00002DA0 5F                  <1> 	POP	eDI
  6829 00002DA1 C3                  <1> 	RETn				; ZERO FLAG IS SET
  6830                              <1> 
  6831                              <1> ;CMD_TIMEOUT:
  6832                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6833                              <1> ;COMMAND4:
  6834                              <1> ;	POP	BX
  6835                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6836                              <1> ;	RETn
  6837                              <1> 
  6838                              <1> ;----------------------------------------
  6839                              <1> ;	WAIT FOR INTERRUPT		:
  6840                              <1> ;----------------------------------------
  6841                              <1> ;WAIT:
  6842                              <1> _WAIT:
  6843 00002DA2 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6844                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6845                              <1> 	;CLC
  6846                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6847                              <1> 	;INT	15H
  6848                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6849                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6850                              <1> 
  6851                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6852                              <1> 	;; 21/02/2015
  6853                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6854                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6855 00002DA3 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6856                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6857                              <1> ;-----	WAIT LOOP
  6858                              <1> 
  6859                              <1> WT1:	
  6860                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6861 00002DA8 F605[B76C0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6862                              <1> 	;LOOPZ	WT1
  6863 00002DAF 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6864                              <1> 	;DEC	BL
  6865                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6866                              <1> 
  6867                              <1> WT1_hi:
  6868 00002DB1 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6869 00002DB3 A810                <1> 	test	al, 10h			; transition on memory
  6870 00002DB5 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6871                              <1> WT1_lo:
  6872 00002DB7 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6873 00002DB9 A810                <1> 	test	al, 10h			
  6874 00002DBB 74FA                <1> 	jz	short WT1_lo
  6875 00002DBD E2E9                <1> 	loop	WT1
  6876                              <1> 	;;or	bl, bl
  6877                              <1> 	;;jz	short WT2	
  6878                              <1> 	;;dec	bl
  6879                              <1> 	;;jmp	short WT1
  6880                              <1> 	;dec	bl
  6881                              <1> 	;jnz	short WT1	
  6882                              <1> 
  6883 00002DBF C605[BF6C0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6884 00002DC6 EB0E                <1> 	JMP	SHORT WT4
  6885 00002DC8 C605[BF6C0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6886 00002DCF C605[B76C0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6887 00002DD6 803D[BF6C0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6888 00002DDD C3                  <1> 	RETn
  6889                              <1> 
  6890                              <1> ;----------------------------------------
  6891                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6892                              <1> ;----------------------------------------
  6893                              <1> NOT_BUSY:
  6894 00002DDE FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6895                              <1> 	;PUSH	eBX
  6896                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6897 00002DDF 668B15[D4660000]    <1> 	mov	DX, [HF_PORT]
  6898 00002DE6 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6899                              <1> 	;MOV	BL,DELAY_1
  6900                              <1> 					; wait for 10 seconds
  6901                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6902                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6903                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6904 00002DE9 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6905                              <1> 	;
  6906                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6907                              <1> NB1:	
  6908 00002DEE EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6909                              <1> 	;TEST	AL,ST_BUSY
  6910 00002DEF 2480                <1> 	and	al, ST_BUSY
  6911                              <1> 	;LOOPNZ	NB1
  6912 00002DF1 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  6913                              <1> 	;DEC	BL			
  6914                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  6915                              <1> 
  6916 00002DF3 E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  6917 00002DF5 A810                <1> 	TEST	AL,010H			; transition on memory
  6918 00002DF7 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  6919 00002DF9 E461                <1> NB1_lo: IN	AL,SYS1
  6920 00002DFB A810                <1> 	TEST	AL,010H
  6921 00002DFD 74FA                <1> 	JZ	short NB1_lo
  6922 00002DFF E2ED                <1> 	LOOP	NB1
  6923                              <1> 	;dec	bl
  6924                              <1> 	;jnz	short NB1
  6925                              <1> 	;
  6926                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6927                              <1> ;;	jb	short NB1
  6928                              <1> 	;
  6929                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  6930                              <1> 	;JMP	SHORT NB3
  6931 00002E01 B080                <1> 	mov	al, TIME_OUT
  6932                              <1> NB2:	
  6933                              <1> 	;MOV	byte [DISK_STATUS1],0
  6934                              <1> ;NB3:	
  6935                              <1> 	;POP	eBX
  6936 00002E03 A2[BF6C0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  6937                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6938 00002E08 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  6939 00002E0A C3                  <1> 	RETn
  6940                              <1> 
  6941                              <1> ;----------------------------------------
  6942                              <1> ;	WAIT FOR DATA REQUEST		:
  6943                              <1> ;----------------------------------------
  6944                              <1> WAIT_DRQ:
  6945                              <1> 	;MOV	CX,DELAY_3
  6946                              <1> 	;MOV	DX,HF_PORT+7
  6947 00002E0B 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6948 00002E12 80C207              <1> 	add	dl, 7
  6949                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  6950                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  6951                              <1> 					; (but it is written as 2000
  6952                              <1> 					; micro seconds in ATORGS.ASM file
  6953                              <1> 					; of Award Bios - 1999, D1A0622)
  6954 00002E15 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  6955 00002E1A EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  6956 00002E1B A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  6957 00002E1D 7516                <1> 	JNZ	short WQ_OK
  6958                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  6959                              <1> WQ_hi:	
  6960 00002E1F E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  6961 00002E21 A810                <1> 	TEST	AL,010H			; transition on memory
  6962 00002E23 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  6963 00002E25 E461                <1> WQ_lo:  IN      AL,SYS1
  6964 00002E27 A810                <1> 	TEST	AL,010H
  6965 00002E29 74FA                <1> 	JZ	SHORT WQ_lo
  6966 00002E2B E2ED                <1> 	LOOP	WQ_1
  6967                              <1> 
  6968 00002E2D C605[BF6C0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  6969 00002E34 F9                  <1> 	STC
  6970                              <1> WQ_OK:
  6971 00002E35 C3                  <1> 	RETn
  6972                              <1> ;WQ_OK:	;CLC
  6973                              <1> ;	RETn
  6974                              <1> 
  6975                              <1> ;----------------------------------------
  6976                              <1> ;	CHECK FIXED DISK STATUS 	:
  6977                              <1> ;----------------------------------------
  6978                              <1> CHECK_STATUS:
  6979 00002E36 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  6980 00002E3B 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  6981 00002E3D A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  6982 00002E3F 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  6983 00002E41 E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  6984                              <1> CHECK_S1:
  6985 00002E46 803D[BF6C0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  6986 00002E4D C3                  <1> 	RETn
  6987                              <1> 
  6988                              <1> ;----------------------------------------
  6989                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  6990                              <1> ;----------------------------------------
  6991                              <1> CHECK_ST:
  6992                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  6993 00002E4E 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]
  6994 00002E55 80C207              <1> 	add	dl, 7
  6995 00002E58 EC                  <1> 	IN	AL,DX
  6996 00002E59 A2[B56C0000]        <1> 	MOV	[HF_STATUS],AL
  6997 00002E5E B400                <1> 	MOV	AH,0
  6998 00002E60 A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  6999 00002E62 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7000 00002E64 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7001 00002E66 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7002 00002E68 7514                <1> 	JNZ	short CKST_EXIT
  7003 00002E6A B4AA                <1> 	MOV	AH,NOT_RDY
  7004 00002E6C A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7005 00002E6E 740E                <1> 	JZ	short CKST_EXIT
  7006 00002E70 B440                <1> 	MOV	AH,BAD_SEEK
  7007 00002E72 A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7008 00002E74 7408                <1> 	JZ	short CKST_EXIT
  7009 00002E76 B411                <1> 	MOV	AH,DATA_CORRECTED
  7010 00002E78 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7011 00002E7A 7502                <1> 	JNZ	short CKST_EXIT
  7012 00002E7C B400                <1> 	MOV	AH,0
  7013                              <1> CKST_EXIT:
  7014 00002E7E 8825[BF6C0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7015 00002E84 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7016 00002E87 7403                <1> 	JZ	short CKST_EX1
  7017 00002E89 80FC00              <1> 	CMP	AH,0
  7018                              <1> CKST_EX1:
  7019 00002E8C C3                  <1> 	RETn
  7020                              <1> 
  7021                              <1> ;----------------------------------------
  7022                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7023                              <1> ;----------------------------------------
  7024                              <1> CHECK_ER:
  7025                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7026 00002E8D 668B15[D4660000]    <1> 	mov	dx, [HF_PORT]		;
  7027 00002E94 FEC2                <1> 	inc	dl
  7028 00002E96 EC                  <1> 	IN	AL,DX
  7029 00002E97 A2[B66C0000]        <1> 	MOV	[HF_ERROR],AL
  7030 00002E9C 53                  <1> 	PUSH	eBX ; 21/02/2015
  7031 00002E9D B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7032 00002EA2 D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7033 00002EA4 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7034 00002EA6 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7035 00002EA8 BB[C8660000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7036 00002EAD 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7037                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7038                              <1> 	;mov	ah, [bx]
  7039 00002EAF 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7040 00002EB1 8825[BF6C0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7041 00002EB7 5B                  <1> 	POP	eBX
  7042 00002EB8 80FC00              <1> 	CMP	AH,0
  7043 00002EBB C3                  <1> 	RETn
  7044                              <1> 
  7045                              <1> ;--------------------------------------------------------
  7046                              <1> ; CHECK_DMA						:
  7047                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7048                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7049                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7050                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7051                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7052                              <1> ;  -ERROR OTHERWISE					:
  7053                              <1> ;--------------------------------------------------------
  7054                              <1> CHECK_DMA:
  7055                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7056                              <1> 	; 24/12/2021
  7057 00002EBC 50                  <1> 	push	eax
  7058 00002EBD 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7059 00002EC1 F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7060 00002EC5 7404                <1> 	JZ	short CKD1
  7061 00002EC7 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7062 00002ECB 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7063 00002ECE 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7064 00002ED0 7207                <1> 	JB	short CKDERR		; TOO MANY
  7065 00002ED2 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7066 00002ED4 7203                <1> 	JB	short CKDERR		; ERROR
  7067 00002ED6 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7068                              <1> 	;POP	AX
  7069                              <1> 	; 24/12/2021
  7070 00002ED7 58                  <1> 	pop	eax
  7071 00002ED8 C3                  <1> 	RETn				; NORMAL RETURN
  7072 00002ED9 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7073 00002EDA C605[BF6C0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7074                              <1> 	;POP	AX
  7075                              <1> 	; 24/12/2021
  7076 00002EE1 58                  <1> 	pop	eax	
  7077 00002EE2 C3                  <1> 	RETn
  7078                              <1> 
  7079                              <1> ;----------------------------------------
  7080                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7081                              <1> ;----------------------------------------
  7082                              <1> 					
  7083                              <1> ; INPUT -> DL = 0 based drive number
  7084                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7085                              <1> 
  7086                              <1> GET_VEC:
  7087                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7088                              <1> 	;MOV	ES,AX
  7089                              <1> 	;TEST	DL,1
  7090                              <1> 	;JZ	short GV_0
  7091                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7092                              <1> ;	JMP	SHORT GV_EXIT
  7093                              <1> ;GV_0:
  7094                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7095                              <1> ;
  7096                              <1> 	;xor	bh, bh
  7097 00002EE3 31DB                <1> 	xor	ebx, ebx
  7098 00002EE5 88D3                <1> 	mov	bl, dl
  7099                              <1> 	;;02/01/2015
  7100                              <1> 	;;shl	bl, 1			; port address offset
  7101                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7102                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7103 00002EE7 C0E302              <1> 	shl	bl, 2	;;
  7104                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7105 00002EEA 81C3[C46C0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7106                              <1> 	;push	word [bx+2]		; dpt segment
  7107                              <1> 	;pop	es
  7108                              <1> 	;mov	bx, [bx]		; dpt offset
  7109 00002EF0 8B1B                <1> 	mov	ebx, [ebx]		
  7110                              <1> ;GV_EXIT:
  7111 00002EF2 C3                  <1> 	RETn
  7112                              <1> 
  7113                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7114                              <1> hdc1_int: ; 21/02/2015
  7115                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7116                              <1> ;								:
  7117                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7118                              <1> ;								:
  7119                              <1> ;----------------------------------------------------------------
  7120                              <1> 
  7121                              <1> ; 22/12/2014
  7122                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7123                              <1> ;	 '11/15/85'
  7124                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7125                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7126                              <1> 
  7127                              <1> ;int_76h:
  7128                              <1> HD_INT:
  7129                              <1> 	;push	ax
  7130                              <1> 	; 24/12/2021
  7131 00002EF3 50                  <1> 	push	eax
  7132 00002EF4 1E                  <1> 	push	ds
  7133                              <1> 	;CALL	DDS
  7134                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7135 00002EF5 66B81000            <1> 	mov	ax, KDATA
  7136 00002EF9 8ED8                <1> 	mov 	ds, ax
  7137                              <1> 	;
  7138                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7139                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7140 00002EFB C605[B76C0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7141                              <1> 	;
  7142                              <1> 	;push	dx
  7143                              <1> 	; 24/12/2021
  7144 00002F02 52                  <1> 	push	edx
  7145 00002F03 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7146                              <1> 					; Clear Controller
  7147                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7148 00002F07 EC                  <1> 	in	al, dx			;
  7149                              <1> 	;pop	dx
  7150                              <1> 	; 24/12/2021
  7151 00002F08 5A                  <1> 	pop	edx
  7152                              <1> 	NEWIODELAY
  2051 00002F09 E6EB                <2>  out 0EBh,al
  7153                              <1> 	;
  7154 00002F0B B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7155 00002F0D E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7156                              <1> 	;JMP	$+2			; WAIT
  7157                              <1> 	NEWIODELAY
  2051 00002F0F E6EB                <2>  out 0EBh,al
  7158 00002F11 E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7159 00002F13 1F                  <1> 	pop	ds
  7160                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7161                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7162                              <1> 	;INT	15H			;  INTERRUPT
  7163                              <1> irq15_iret: ; 25/02/2015
  7164                              <1> 	;pop	ax
  7165                              <1> 	; 24/12/2021
  7166 00002F14 58                  <1> 	pop	eax
  7167 00002F15 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7168                              <1> 
  7169                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7170                              <1> hdc2_int: ; 21/02/2015
  7171                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7172                              <1> ;								:
  7173                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7174                              <1> ;								:
  7175                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7176                              <1> 
  7177                              <1> ;int_77h:
  7178                              <1> HD1_INT:
  7179                              <1> 	;push	ax
  7180                              <1> 	; 24/12/2021
  7181 00002F16 50                  <1> 	push	eax
  7182                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7183                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7184 00002F17 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7185 00002F19 E6A0                <1> 	out	0A0h, al
  7186 00002F1B EB00                <1>         jmp short $+2
  7187 00002F1D EB00                <1> 	jmp short $+2
  7188 00002F1F E4A0                <1> 	in	al, 0A0h
  7189 00002F21 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7190 00002F23 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7191                              <1> 	;
  7192 00002F25 1E                  <1> 	push	ds
  7193                              <1> 	;CALL	DDS
  7194                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7195 00002F26 66B81000            <1> 	mov	ax, KDATA
  7196 00002F2A 8ED8                <1> 	mov 	ds, ax
  7197                              <1> 	;
  7198                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7199                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7200 00002F2C 800D[B76C0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7201                              <1> 	;
  7202                              <1> 	;push	dx
  7203                              <1> 	; 24/12/2021
  7204 00002F33 52                  <1> 	push	edx
  7205 00002F34 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7206                              <1> 					; Clear Controller (Award BIOS 1999)
  7207 00002F38 EBCD                <1> 	jmp	short Clear_IRQ1415
  7208                              <1> 
  7209                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7210                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7211                              <1> 
  7212                              <1> ;////////////////////////////////////////////////////////////////////
  7213                              <1> ;; END OF DISK I/O SYTEM ///
  1990                                  %include 'memory.inc'  ; 09/03/2015
  1991                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  1992                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.1) - MEMORY.INC
  1993                              <1> ; Last Modification: 31/12/2021
  1994                              <1> ;
  1995                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  1996                              <1> 
  1997                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  1998                              <1> 
  1999                              <1> ;;04/11/2014 (unix386.s)	
  2000                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2001                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2002                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2003                              <1> ;;
  2004                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2005                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2006                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2007                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2008                              <1> 
  2009                              <1> ; 27/04/2015
  2010                              <1> ; 09/03/2015
  2011                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2012                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2013                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2014                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2015                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2016                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2017                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2018                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2019                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2020                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2021                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2022                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2023                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2024                              <1> SWP_DISK_READ_ERR 	   equ 40
  2025                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2026                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2027                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2028                              <1> SWP_DISK_WRITE_ERR         equ 44
  2029                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2030                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2031                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2032                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2033                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2034                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2035                              <1> 					; (Indicates that the page is not allocated
  2036                              <1> 					; for the process, it is a shared or system
  2037                              <1>                                         ; page, it must not be deallocated!)
  2038                              <1> ; 14/12/2020
  2039                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2040                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2041                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2042                              <1> 				; (Out of memory allocation table)	
  2043                              <1> ;
  2044                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2045                              <1> ;;
  2046                              <1> ;; 10/10/2014
  2047                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2048                              <1> ;;
  2049                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2050                              <1> ;;	(virtual address = physical address)
  2051                              <1> ;; KERNEL PAGE TABLES:
  2052                              <1> ;;	Kernel page directory and all page tables are
  2053                              <1> ;;	on memory as initialized, as equal to physical memory
  2054                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2055                              <1> ;;
  2056                              <1> ;;	what for: User pages may be swapped out, when accessing
  2057                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2058                              <1> ;;	kernel would have to swap it in! But it is also may be
  2059                              <1> ;;	in use by a user process. (In system/kernel mode
  2060                              <1> ;;	kernel can access all memory pages even if they are
  2061                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2062                              <1> ;;	cause conflicts.) 
  2063                              <1> ;;	
  2064                              <1> ;;	As result of these conditions,
  2065                              <1> ;;	all kernel pages must be initialized as equal to 
  2066                              <1> ;;	physical layout for preventing page faults. 
  2067                              <1> ;;	Also, calling "allocate page" procedure after
  2068                              <1> ;;	a page fault can cause another page fault (double fault)
  2069                              <1> ;;	if all kernel page tables would not be initialized.
  2070                              <1> ;;
  2071                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2072                              <1> ;;	memory allocation table. (double word aligned)
  2073                              <1> ;;
  2074                              <1> ;;	[next_page] = first/next free space to be searched
  2075                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2076                              <1> ;;
  2077                              <1> ;;	[last_page] = End of memory (users space), as offset
  2078                              <1> ;;	to memory allocation table. (double word aligned)
  2079                              <1> ;;
  2080                              <1> ;; USER PAGE TABLES:
  2081                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2082                              <1> ;;		'ready only' marked copies of the 
  2083                              <1> ;;		parent process's page table entries (for
  2084                              <1> ;;		same physical memory).
  2085                              <1> ;;		(A page will be copied to a new page after
  2086                              <1> ;;		 if it causes R/W page fault.)
  2087                              <1> ;;
  2088                              <1> ;;	Every user process has own (different)
  2089                              <1> ;;	page directory and page tables.	
  2090                              <1> ;;
  2091                              <1> ;;	Code starts at virtual address 0, always.
  2092                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2093                              <1> ;;	(Programs can be written/developed as simple
  2094                              <1> ;;	 flat memory programs.)
  2095                              <1> ;;
  2096                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2097                              <1> ;;	Memory page will be allocated by kernel only 
  2098                              <1> ;;		(in kernel/system mode only).
  2099                              <1> ;;	* After a
  2100                              <1> ;;	  - 'not present' page fault
  2101                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2102                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2103                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2104                              <1> ;;	  request by running process.
  2105                              <1> ;;	* While creating a process, allocating a new buffer,
  2106                              <1> ;;	  new page tables etc.
  2107                              <1> ;;
  2108                              <1> ;;	At first,
  2109                              <1> ;;	- 'allocate page' procedure will be called;
  2110                              <1> ;,	   if it will return with a valid (>0) physical address
  2111                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2112                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2113                              <1> ;;	- 'allocate page' will be called for allocating page
  2114                              <1> ;;	   directory, page table and running space (data/code).
  2115                              <1> ;;	- every successful 'allocate page' call will decrease
  2116                              <1> ;;	  'free_pages' count (pointer).
  2117                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2118                              <1> ;;	  if 'free_pages' points to a ZERO.
  2119                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2120                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2121                              <1> ;;	  error except errors caused by attribute conflicts.
  2122                              <1> ;;	 (swapper functions)	 
  2123                              <1> ;;					
  2124                              <1> ;;	At second,
  2125                              <1> ;;	- page directory entry will be updated then page table
  2126                              <1> ;;	  entry will be updated.		
  2127                              <1> ;;
  2128                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2129                              <1> ;;	- M.A.T. has a size according to available memory as
  2130                              <1> ;;	  follows:
  2131                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2132                              <1> ;;		  - a bit with value of 0 means allocated page
  2133                              <1> ;;		  - a bit with value of 1 means a free page
  2134                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2135                              <1> ;;	  depending on M.A.T.
  2136                              <1> ;;		(NOTE: Free page count will not be checked
  2137                              <1> ;;		again -on M.A.T.- after initialization. 
  2138                              <1> ;;		Kernel will trust on initial count.)
  2139                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2140                              <1> ;;	  and it will be increased by deallocation procedures.
  2141                              <1> ;;	
  2142                              <1> ;;	- Available memory will be calculated during
  2143                              <1> ;;	  the kernel's initialization stage (in real mode).
  2144                              <1> ;;	  Memory allocation table and kernel page tables 
  2145                              <1> ;;	  will be formatted/sized as result of available
  2146                              <1> ;;	  memory calculation before paging is enabled.
  2147                              <1> ;;
  2148                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2149                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2150                              <1> ;;	- Memory allocation for kernel page directory size 
  2151                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2152                              <1> ;;	  for page tables)
  2153                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2154                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2155                              <1> ;;	- User (available) space will be started 
  2156                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2157                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2158                              <1> ;;	  memory allocation table and kernel's page directory
  2159                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2160                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2161                              <1> ;; 	  for buffers.
  2162                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2163                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2164                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2165                              <1> ;;
  2166                              <1> ;; For 1GB Available Memory:
  2167                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2168                              <1> ;;	- Memory allocation for kernel page directory size 
  2169                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2170                              <1> ;;	  for page tables)
  2171                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2172                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2173                              <1> ;;	- User (available) space will be started 
  2174                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2175                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2176                              <1> ;;	  memory allocation table and kernel's page directory
  2177                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2178                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2179                              <1> ;; 	  for buffers.
  2180                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2181                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2182                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2183                              <1> ;;
  2184                              <1> ;;
  2185                              <1> 
  2186                              <1> ;;************************************************************************************
  2187                              <1> ;; 
  2188                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2189                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2190                              <1> 
  2191                              <1> ;; Main factor: "sys fork" system call 
  2192                              <1> ;;	
  2193                              <1> ;; 		FORK
  2194                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2195                              <1> ;;  writable pages ---->|
  2196                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2197                              <1> ;; 
  2198                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2199                              <1> ;; 
  2200                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2201                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2202                              <1> ;;       -while R/W bit is 0-. 
  2203                              <1> ;; 
  2204                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2205                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2206                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2207                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2208                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2209                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2210                              <1> ;; 
  2211                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2212                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2213                              <1> ;;   Parent's PTE attributes are not changed.
  2214                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2215                              <1> ;;    destroy/mix previous fork result).
  2216                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2217                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2218                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2219                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2220                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2221                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2222                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2223                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2224                              <1> ;; 
  2225                              <1> ;; !? WHAT FOR (duplication after duplication):
  2226                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2227                              <1> ;; program/executable code continues from specified location as child process, 
  2228                              <1> ;; returns back previous code location as parent process, every child after 
  2229                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2230                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2231                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2232                              <1> ;; was copied to child's process segment (all of code and data) according to
  2233                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2234                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2235                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2236                              <1> ;; (complete running image of parent process) to the child process; 
  2237                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2238                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2239                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2240                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2241                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2242                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2243                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2244                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2245                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2246                              <1> ;; for sharing same read only pages between parent and child processes.
  2247                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2248                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2249                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2250                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2251                              <1> ;; -deallocation problem-.
  2252                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2253                              <1> ;; 
  2254                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2255                              <1> ;; # Page fault handler will do those:
  2256                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2257                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2258                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2259                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2260                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2261                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2262                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2263                              <1> ;;     to child process.)	
  2264                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2265                              <1> ;; # Page fault handler will do those:
  2266                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2267                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2268                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2269                              <1> ;;     address or not. 
  2270                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2271                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2272                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2273                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2274                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2275                              <1> ;; 
  2276                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2277                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2278                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2279                              <1> ;;       duplication method details, it is not possible multiple child processes
  2280                              <1> ;;       were using same page with duplicated PTEs.
  2281                              <1> ;; 
  2282                              <1> ;;************************************************************************************   
  2283                              <1> 
  2284                              <1> ;; 08/10/2014
  2285                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2286                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2287                              <1> 
  2288                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2289                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2290                              <1> ;; (25/08/2014, Revision: 5057) file 
  2291                              <1> ;; by KolibriOS Team (2004-2012)
  2292                              <1> 
  2293                              <1> allocate_page:
  2294                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2295                              <1> 	; 01/07/2015
  2296                              <1> 	; 05/05/2015
  2297                              <1> 	; 30/04/2015
  2298                              <1> 	; 16/10/2014
  2299                              <1> 	; 08/10/2014
  2300                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2301                              <1> 	;
  2302                              <1> 	; INPUT -> none
  2303                              <1> 	;
  2304                              <1> 	; OUTPUT ->
  2305                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2306                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2307                              <1> 	;
  2308                              <1> 	;	CF = 1 and EAX = 0 
  2309                              <1> 	; 		   if there is not a free page to be allocated	
  2310                              <1> 	;
  2311                              <1> 	; Modified Registers -> none (except EAX)
  2312                              <1> 	;
  2313 00002F3A A1[306C0000]        <1> 	mov	eax, [free_pages]
  2314 00002F3F 21C0                <1> 	and	eax, eax
  2315 00002F41 7438                <1> 	jz	short out_of_memory
  2316                              <1> 	;
  2317 00002F43 53                  <1> 	push	ebx
  2318 00002F44 51                  <1> 	push	ecx
  2319                              <1> 	;
  2320 00002F45 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2321 00002F4A 89D9                <1> 	mov	ecx, ebx
  2322                              <1>  				     ; NOTE: 32 (first_page) is initial
  2323                              <1> 				     ; value of [next_page].
  2324                              <1> 				     ; It points to the first available
  2325                              <1> 				     ; page block for users (ring 3) ...	
  2326                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2327                              <1> 				     ; (at the of the first 4 MB)		
  2328 00002F4C 031D[346C0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2329                              <1> 				 ; next_free_page >> 5
  2330 00002F52 030D[386C0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2331                              <1> 				 ; (total_pages - 1) >> 5
  2332                              <1> al_p_scan:
  2333 00002F58 39CB                <1> 	cmp	ebx, ecx
  2334 00002F5A 770A                <1> 	ja	short al_p_notfound
  2335                              <1> 	;
  2336                              <1> 	; 01/07/2015
  2337                              <1> 	; AMD64 Architecture Programmers Manual
  2338                              <1> 	; Volume 3:
  2339                              <1> 	; General-Purpose and System Instructions
  2340                              <1> 	;
  2341                              <1> 	; BSF - Bit Scan Forward
  2342                              <1> 	;
  2343                              <1> 	;   Searches the value in a register or a memory location
  2344                              <1> 	;   (second operand) for the least-significant set bit. 
  2345                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2346                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2347                              <1> 	;   register (first operand). If the second operand contains 0, 
  2348                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2349                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2350                              <1> 	;   of the searched value
  2351                              <1> 	;
  2352 00002F5C 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2353                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2354                              <1> 			   ; loads the destination with an index to
  2355                              <1> 			   ; first set bit. (0 -> 31) 
  2356                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2357 00002F5F 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2358                              <1> 			 ;
  2359                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2360                              <1> 			 ;	  with value of 1 means 
  2361                              <1> 			 ;	  the corresponding page is free 
  2362                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2363 00002F61 83C304              <1> 	add	ebx, 4
  2364                              <1> 			 ; We return back for searching next page block
  2365                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2366                              <1> 			 ;	 we always will find at least 1 free page here.
  2367 00002F64 EBF2                <1>         jmp     short al_p_scan
  2368                              <1> 	;
  2369                              <1> al_p_notfound:
  2370 00002F66 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2371 00002F6C 890D[346C0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2372                              <1> 				 ; (deallocate_page procedure will change it)
  2373 00002F72 31C0                <1> 	xor	eax, eax
  2374 00002F74 A3[306C0000]        <1> 	mov	[free_pages], eax ; 0
  2375 00002F79 59                  <1> 	pop	ecx
  2376 00002F7A 5B                  <1> 	pop	ebx
  2377                              <1> 	;
  2378                              <1> ; 24/12/2021
  2379                              <1> ; ('swap_out' procedure call is disabled)
  2380                              <1> 
  2381                              <1> out_of_memory:
  2382                              <1> ;	call	swap_out
  2383                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2384                              <1> ;	;
  2385                              <1> ;	sub 	eax, eax ; 0
  2386 00002F7B F9                  <1> 	stc
  2387 00002F7C C3                  <1> 	retn
  2388                              <1> 
  2389                              <1> al_p_found:
  2390 00002F7D 89D9                <1> 	mov	ecx, ebx
  2391 00002F7F 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2392 00002F85 890D[346C0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2393                              <1> 				 ; address/offset (to the next)
  2394 00002F8B FF0D[306C0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2395                              <1> 	;
  2396 00002F91 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2397                              <1> 				 ; is copied into the Carry Flag and then cleared
  2398                              <1> 				 ; in the destination.
  2399                              <1> 				 ;
  2400                              <1> 				 ; Reset the bit which is corresponding to the 
  2401                              <1> 				 ; (just) allocated page.
  2402                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2403 00002F94 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2404 00002F97 01C8                <1> 	add	eax, ecx	 ; = page number
  2405 00002F99 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2406                              <1> 	; EAX = physical address of memory page
  2407                              <1> 	;
  2408                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2409                              <1> 	;       according to this EAX value...
  2410 00002F9C 59                  <1> 	pop	ecx
  2411 00002F9D 5B                  <1> 	pop	ebx
  2412                              <1> al_p_ok:
  2413 00002F9E C3                  <1> 	retn
  2414                              <1> 
  2415                              <1> make_page_dir:
  2416                              <1> 	; 18/04/2015
  2417                              <1> 	; 12/04/2015
  2418                              <1> 	; 23/10/2014
  2419                              <1> 	; 16/10/2014
  2420                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2421                              <1> 	;
  2422                              <1> 	; INPUT ->
  2423                              <1> 	;	none
  2424                              <1> 	; OUTPUT ->
  2425                              <1> 	;	(EAX = 0)
  2426                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2427                              <1> 	;	cf = 0 ->
  2428                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2429                              <1> 	;		  process/user.
  2430                              <1> 	;
  2431                              <1> 	; Modified Registers -> EAX
  2432                              <1> 	;
  2433 00002F9F E896FFFFFF          <1> 	call	allocate_page
  2434 00002FA4 7216                <1> 	jc	short mkpd_error
  2435                              <1> 	;
  2436 00002FA6 A3[61700000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2437                              <1> 				  ; (Physical address)
  2438                              <1> clear_page:
  2439                              <1> 	; 18/04/2015
  2440                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2441                              <1> 	;
  2442                              <1> 	; INPUT ->
  2443                              <1> 	;	EAX = physical address of the page
  2444                              <1> 	; OUTPUT ->
  2445                              <1> 	;	all bytes of the page will be cleared
  2446                              <1> 	;
  2447                              <1> 	; Modified Registers -> none
  2448                              <1> 	;
  2449 00002FAB 57                  <1> 	push	edi
  2450 00002FAC 51                  <1> 	push	ecx
  2451 00002FAD 50                  <1> 	push	eax
  2452 00002FAE B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2453 00002FB3 89C7                <1> 	mov	edi, eax
  2454 00002FB5 31C0                <1> 	xor	eax, eax
  2455 00002FB7 F3AB                <1> 	rep	stosd
  2456 00002FB9 58                  <1> 	pop	eax
  2457 00002FBA 59                  <1> 	pop	ecx
  2458 00002FBB 5F                  <1> 	pop	edi
  2459                              <1> mkpd_error:
  2460                              <1> mkpt_error:
  2461 00002FBC C3                  <1> 	retn
  2462                              <1> 
  2463                              <1> make_page_table:
  2464                              <1> 	; 23/06/2015
  2465                              <1> 	; 18/04/2015
  2466                              <1> 	; 12/04/2015
  2467                              <1> 	; 16/10/2014
  2468                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2469                              <1> 	;
  2470                              <1> 	; INPUT ->
  2471                              <1> 	;	EBX = virtual (linear) address
  2472                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2473                              <1> 	;	      (higher 20 bits must be ZERO)
  2474                              <1> 	;	      (bit 0 must be 1)	 
  2475                              <1> 	;	u.pgdir = page directory (physical) address
  2476                              <1> 	; OUTPUT ->
  2477                              <1> 	;	EDX = Page directory entry address
  2478                              <1> 	;	EAX = Page table address
  2479                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2480                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2481                              <1> 	;
  2482                              <1> 	; Modified Registers -> EAX, EDX
  2483                              <1> 	;
  2484 00002FBD E878FFFFFF          <1> 	call	allocate_page
  2485 00002FC2 72F8                <1> 	jc	short mkpt_error
  2486 00002FC4 E811000000          <1> 	call	set_pde	
  2487 00002FC9 EBE0                <1> 	jmp	short clear_page
  2488                              <1> 
  2489                              <1> make_page:
  2490                              <1> 	; 24/07/2015
  2491                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2492                              <1> 	;
  2493                              <1> 	; INPUT ->
  2494                              <1> 	;	EBX = virtual (linear) address
  2495                              <1> 	;	ECX = page attributes (lower 12 bits)
  2496                              <1> 	;	      (higher 20 bits must be ZERO)
  2497                              <1> 	;	      (bit 0 must be 1)	 
  2498                              <1> 	;	u.pgdir = page directory (physical) address
  2499                              <1> 	; OUTPUT ->
  2500                              <1> 	;	EBX = Virtual address
  2501                              <1> 	;	(EDX = PTE value)
  2502                              <1> 	;	EAX = Physical address
  2503                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2504                              <1> 	;
  2505                              <1> 	; Modified Registers -> EAX, EDX
  2506                              <1> 	;
  2507 00002FCB E86AFFFFFF          <1> 	call	allocate_page
  2508 00002FD0 7207                <1> 	jc	short mkp_err
  2509 00002FD2 E821000000          <1> 	call	set_pte	
  2510 00002FD7 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2511                              <1> mkp_err:
  2512 00002FD9 C3                  <1> 	retn
  2513                              <1> 
  2514                              <1> set_pde:	; Set page directory entry (PDE)
  2515                              <1> 	; 20/07/2015
  2516                              <1> 	; 18/04/2015
  2517                              <1> 	; 12/04/2015
  2518                              <1> 	; 23/10/2014
  2519                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2520                              <1> 	;
  2521                              <1> 	; INPUT ->
  2522                              <1> 	;	EAX = physical address
  2523                              <1> 	;	      (use present value if EAX = 0)
  2524                              <1> 	;	EBX = virtual (linear) address
  2525                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2526                              <1> 	;	      (higher 20 bits must be ZERO)
  2527                              <1> 	;	      (bit 0 must be 1)	 
  2528                              <1> 	;	u.pgdir = page directory (physical) address
  2529                              <1> 	; OUTPUT ->
  2530                              <1> 	;	EDX = PDE address
  2531                              <1> 	;	EAX = page table address (physical)
  2532                              <1> 	;	;(CF=1 -> Invalid page address)
  2533                              <1> 	;
  2534                              <1> 	; Modified Registers -> EDX
  2535                              <1> 	;
  2536 00002FDA 89DA                <1> 	mov	edx, ebx
  2537 00002FDC C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2538 00002FDF C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2539 00002FE2 0315[61700000]      <1> 	add	edx, [u.pgdir]
  2540                              <1> 	;
  2541 00002FE8 21C0                <1> 	and	eax, eax
  2542 00002FEA 7506                <1> 	jnz	short spde_1
  2543                              <1> 	;
  2544 00002FEC 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2545                              <1> 	;test	al, 1
  2546                              <1> 	;jz	short spde_2
  2547 00002FEE 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2548                              <1> spde_1:
  2549                              <1> 	;and	cx, 0FFFh
  2550 00002FF2 8902                <1> 	mov	[edx], eax
  2551 00002FF4 66090A              <1> 	or	[edx], cx
  2552 00002FF7 C3                  <1> 	retn
  2553                              <1> ;spde_2: ; error
  2554                              <1> ;	stc
  2555                              <1> ;	retn
  2556                              <1> 
  2557                              <1> set_pte:	; Set page table entry (PTE)
  2558                              <1> 	; 24/07/2015
  2559                              <1> 	; 20/07/2015
  2560                              <1> 	; 23/06/2015
  2561                              <1> 	; 18/04/2015
  2562                              <1> 	; 12/04/2015
  2563                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2564                              <1> 	;
  2565                              <1> 	; INPUT ->
  2566                              <1> 	;	EAX = physical page address
  2567                              <1> 	;	      (use present value if EAX = 0)
  2568                              <1> 	;	EBX = virtual (linear) address
  2569                              <1> 	;	ECX = page attributes (lower 12 bits)
  2570                              <1> 	;	      (higher 20 bits must be ZERO)
  2571                              <1> 	;	      (bit 0 must be 1)	 
  2572                              <1> 	;	u.pgdir = page directory (physical) address
  2573                              <1> 	; OUTPUT ->
  2574                              <1> 	;	EAX = physical page address
  2575                              <1> 	;	(EDX = PTE value)
  2576                              <1> 	;	EBX = virtual address
  2577                              <1> 	;
  2578                              <1> 	;	CF = 1 -> error
  2579                              <1> 	;
  2580                              <1> 	; Modified Registers -> EAX, EDX
  2581                              <1> 	;
  2582 00002FF8 50                  <1> 	push	eax
  2583 00002FF9 A1[61700000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2584 00002FFE E837000000          <1> 	call 	get_pde
  2585                              <1> 		; EDX = PDE address
  2586                              <1> 		; EAX = PDE value
  2587 00003003 5A                  <1> 	pop	edx ; physical page address
  2588 00003004 722A                <1> 	jc	short spte_err ; PDE not present
  2589                              <1> 	;
  2590 00003006 53                  <1> 	push	ebx ; 24/07/2015
  2591 00003007 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2592                              <1> 			    ; EDX = PT address (physical)	
  2593 0000300B C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2594 0000300E 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2595                              <1> 			 ; clear higher 10 bits (PD bits)
  2596 00003014 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2597 00003017 01C3                <1> 	add	ebx, eax
  2598                              <1> 	;
  2599 00003019 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2600 0000301B A801                <1> 	test	al, 1
  2601 0000301D 740C                <1> 	jz	short spte_0
  2602 0000301F 09D2                <1> 	or	edx, edx
  2603 00003021 750F                <1> 	jnz	short spte_1
  2604 00003023 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2605 00003027 89C2                <1> 	mov	edx, eax
  2606 00003029 EB09                <1> 	jmp	short spte_2	
  2607                              <1> spte_0:
  2608                              <1> 	; If this PTE contains a swap (disk) address,
  2609                              <1> 	; it can be updated by using 'swap_in' procedure
  2610                              <1> 	; only!
  2611 0000302B 21C0                <1> 	and	eax, eax
  2612 0000302D 7403                <1> 	jz	short spte_1
  2613                              <1> 	; 24/07/2015
  2614                              <1> 	; swapped page ! (on disk)
  2615 0000302F 5B                  <1> 	pop	ebx
  2616                              <1> spte_err:
  2617 00003030 F9                  <1> 	stc
  2618 00003031 C3                  <1> 	retn
  2619                              <1> spte_1: 
  2620 00003032 89D0                <1> 	mov	eax, edx
  2621                              <1> spte_2:
  2622 00003034 09CA                <1> 	or	edx, ecx
  2623                              <1> 	; 23/06/2015
  2624 00003036 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2625                              <1> 	; 24/07/2015
  2626 00003038 5B                  <1> 	pop	ebx
  2627 00003039 C3                  <1> 	retn
  2628                              <1> 
  2629                              <1> get_pde:	; Get present value of the relevant PDE
  2630                              <1> 	; 20/07/2015
  2631                              <1> 	; 18/04/2015
  2632                              <1> 	; 12/04/2015
  2633                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2634                              <1> 	;
  2635                              <1> 	; INPUT ->
  2636                              <1> 	;	EBX = virtual (linear) address
  2637                              <1> 	;	EAX = page directory (physical) address
  2638                              <1> 	; OUTPUT ->
  2639                              <1> 	;	EDX = Page directory entry address
  2640                              <1> 	;	EAX = Page directory entry value
  2641                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2642                              <1> 	; Modified Registers -> EDX, EAX
  2643                              <1> 	;
  2644 0000303A 89DA                <1> 	mov	edx, ebx
  2645 0000303C C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2646 0000303F C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2647 00003042 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2648 00003044 8B02                <1> 	mov	eax, [edx]
  2649 00003046 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2650 00003048 751F                <1> 	jnz	short gpte_retn
  2651 0000304A F9                  <1> 	stc
  2652                              <1> gpde_retn:	
  2653 0000304B C3                  <1> 	retn
  2654                              <1> 
  2655                              <1> get_pte:
  2656                              <1> 		; Get present value of the relevant PTE
  2657                              <1> 	; 29/07/2015
  2658                              <1> 	; 20/07/2015
  2659                              <1> 	; 18/04/2015
  2660                              <1> 	; 12/04/2015
  2661                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2662                              <1> 	;
  2663                              <1> 	; INPUT ->
  2664                              <1> 	;	EBX = virtual (linear) address
  2665                              <1> 	;	EAX = page directory (physical) address
  2666                              <1> 	; OUTPUT ->
  2667                              <1> 	;	EDX = Page table entry address (if CF=0)
  2668                              <1> 	;	      Page directory entry address (if CF=1)
  2669                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2670                              <1> 	;	EAX = Page table entry value (page address)
  2671                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2672                              <1> 	; Modified Registers -> EAX, EDX
  2673                              <1> 	;
  2674 0000304C E8E9FFFFFF          <1> 	call 	get_pde
  2675 00003051 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2676                              <1> 	;jnc	short gpte_1
  2677                              <1> 	;retn
  2678                              <1> ;gpte_1:
  2679 00003053 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2680 00003057 89DA                <1> 	mov	edx, ebx
  2681 00003059 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2682 0000305C 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2683                              <1> 			 ; clear higher 10 bits (PD bits)
  2684 00003062 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2685 00003065 01C2                <1> 	add	edx, eax
  2686 00003067 8B02                <1> 	mov	eax, [edx]
  2687                              <1> gpte_retn:
  2688 00003069 C3                  <1> 	retn
  2689                              <1> 
  2690                              <1> deallocate_page_dir:
  2691                              <1> 	; 15/09/2015
  2692                              <1> 	; 05/08/2015
  2693                              <1> 	; 30/04/2015
  2694                              <1> 	; 28/04/2015
  2695                              <1> 	; 17/10/2014
  2696                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2697                              <1> 	;
  2698                              <1> 	; INPUT ->
  2699                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2700                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2701                              <1> 	; OUTPUT ->
  2702                              <1> 	;	All of page tables in the page directory
  2703                              <1> 	;	and page dir's itself will be deallocated
  2704                              <1> 	;	except 'read only' duplicated pages (will be converted
  2705                              <1> 	;	to writable pages).
  2706                              <1> 	;
  2707                              <1> 	; Modified Registers -> EAX
  2708                              <1> 	;
  2709                              <1> 	;
  2710 0000306A 56                  <1> 	push	esi
  2711 0000306B 51                  <1> 	push	ecx
  2712 0000306C 50                  <1> 	push	eax
  2713 0000306D 89C6                <1> 	mov	esi, eax 
  2714 0000306F 31C9                <1> 	xor	ecx, ecx
  2715                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2716                              <1> 	; it must not be deallocated
  2717 00003071 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2718                              <1> dapd_0:
  2719 00003073 AD                  <1> 	lodsd
  2720 00003074 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2721 00003076 7409                <1> 	jz	short dapd_1	
  2722 00003078 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2723 0000307C E812000000          <1> 	call	deallocate_page_table			
  2724                              <1> dapd_1:
  2725 00003081 41                  <1> 	inc	ecx ; page directory entry index
  2726 00003082 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2727 00003088 72E9                <1> 	jb	short dapd_0
  2728                              <1> dapd_2:
  2729 0000308A 58                  <1> 	pop	eax
  2730 0000308B E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2731 00003090 59                  <1> 	pop	ecx
  2732 00003091 5E                  <1> 	pop	esi
  2733 00003092 C3                  <1> 	retn
  2734                              <1> 
  2735                              <1> deallocate_page_table:
  2736                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2737                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2738                              <1> 	; 19/09/2015
  2739                              <1> 	; 15/09/2015
  2740                              <1> 	; 05/08/2015
  2741                              <1> 	; 30/04/2015
  2742                              <1> 	; 28/04/2015
  2743                              <1> 	; 24/10/2014
  2744                              <1> 	; 23/10/2014
  2745                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2746                              <1> 	;
  2747                              <1> 	; INPUT ->
  2748                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2749                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2750                              <1> 	;	(ECX = page directory entry index)
  2751                              <1> 	; OUTPUT ->
  2752                              <1> 	;	All of pages in the page table and page table's itself
  2753                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2754                              <1> 	;	(will be converted to writable pages).
  2755                              <1> 	;
  2756                              <1> 	; Modified Registers -> EAX
  2757                              <1> 	;
  2758 00003093 56                  <1> 	push	esi
  2759 00003094 57                  <1> 	push	edi
  2760 00003095 52                  <1> 	push	edx
  2761 00003096 50                  <1> 	push	eax ; *
  2762 00003097 89C6                <1> 	mov	esi, eax 
  2763 00003099 31FF                <1> 	xor	edi, edi ; 0
  2764                              <1> dapt_0:
  2765 0000309B AD                  <1> 	lodsd
  2766 0000309C A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2767 0000309E 7455                <1> 	jz	short dapt_1
  2768                              <1> 	;
  2769 000030A0 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2770                              <1> 				  ; (must be 1)
  2771 000030A2 753F                <1> 	jnz	short dapt_3
  2772                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2773 000030A4 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2774                              <1> 				   ; as child's page ?
  2775 000030A8 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2776                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2777                              <1> 	; ECX = page directory entry index (0-1023)
  2778 000030AA 53                  <1> 	push	ebx
  2779 000030AB 51                  <1> 	push	ecx
  2780 000030AC 66C1E102            <1> 	shl	cx, 2 ; *4 
  2781 000030B0 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2782 000030B2 8B0B                <1> 	mov	ecx, [ebx]
  2783 000030B4 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2784 000030B7 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2785 000030B9 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2786                              <1> 	; EDI = page table entry index (0-1023)
  2787 000030BE 89FA                <1> 	mov	edx, edi 
  2788 000030C0 66C1E202            <1> 	shl	dx, 2 ; *4 
  2789 000030C4 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2790 000030C6 8B1A                <1> 	mov	ebx, [edx]
  2791 000030C8 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2792 000030CB 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2793 000030CD 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2794 000030D1 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2795 000030D6 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2796 000030D8 7507                <1> 	jne	short dapt_2	; not same page
  2797                              <1> 				; deallocate the child's page
  2798 000030DA 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2799 000030DD 59                  <1> 	pop	ecx
  2800 000030DE 5B                  <1> 	pop	ebx
  2801 000030DF EB0D                <1> 	jmp	short dapt_4
  2802                              <1> 
  2803                              <1> ; 24/12/2021
  2804                              <1> ; ('dapt_1' is disabled)
  2805                              <1> ;
  2806                              <1> ;dapt_1:
  2807                              <1> ;	or	eax, eax	; swapped page ?
  2808                              <1> ;	jz	short dapt_5	; no
  2809                              <1> ;				; yes
  2810                              <1> ;	shr	eax, 1
  2811                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2812                              <1> ;				  ; on the swap disk (or in file)
  2813                              <1> ;	jmp	short dapt_5
  2814                              <1> dapt_2:
  2815 000030E1 59                  <1> 	pop	ecx
  2816 000030E2 5B                  <1> 	pop	ebx
  2817                              <1> dapt_3:	
  2818                              <1> 	; 12/07/2016
  2819 000030E3 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2820 000030E7 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2821                              <1> 	;
  2822                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2823 000030E9 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2824                              <1> dapt_4:
  2825 000030EE C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2826                              <1> dapt_1:	; 24/12/2021
  2827                              <1> dapt_5:
  2828 000030F5 47                  <1> 	inc	edi ; page table entry index
  2829 000030F6 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2830 000030FC 729D                <1> 	jb	short dapt_0
  2831                              <1> 	;
  2832 000030FE 58                  <1> 	pop	eax ; *
  2833 000030FF 5A                  <1> 	pop	edx
  2834 00003100 5F                  <1> 	pop	edi	
  2835 00003101 5E                  <1> 	pop	esi
  2836                              <1> 	;
  2837                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2838                              <1> 	;retn
  2839                              <1> 
  2840                              <1> deallocate_page:
  2841                              <1> 	; 15/09/2015
  2842                              <1> 	; 28/04/2015
  2843                              <1> 	; 10/03/2015
  2844                              <1> 	; 17/10/2014
  2845                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2846                              <1> 	;
  2847                              <1> 	; INPUT -> 
  2848                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2849                              <1> 	; OUTPUT ->
  2850                              <1> 	;	[free_pages] is increased
  2851                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2852                              <1> 	;	CF = 1 if the page is already deallocated
  2853                              <1> 	; 	       (or not allocated) before.  
  2854                              <1> 	;
  2855                              <1> 	; Modified Registers -> EAX
  2856                              <1> 	;
  2857 00003102 53                  <1> 	push	ebx
  2858 00003103 52                  <1> 	push	edx
  2859                              <1> 	;
  2860 00003104 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2861                              <1> 				     ; 12 bits right
  2862                              <1> 				     ; to get page number
  2863 00003107 89C2                <1> 	mov	edx, eax
  2864                              <1> 	; 15/09/2015
  2865 00003109 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2866                              <1> 				     ; (1 allocation bit = 1 page)
  2867                              <1> 				     ; (1 allocation bytes = 8 pages)
  2868 0000310C 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2869                              <1> 				     ; (to get 32 bit position)			
  2870                              <1> 	;
  2871 0000310F BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2872 00003114 01D3                <1> 	add	ebx, edx
  2873 00003116 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2874                              <1> 				     ; (allocation bit position)	 
  2875 00003119 3B15[346C0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2876                              <1> 				     ; than the address in 'next_page' ?
  2877                              <1> 				     ; (next/first free page value)		
  2878 0000311F 7306                <1> 	jnb	short dap_1	     ; no	
  2879 00003121 8915[346C0000]      <1> 	mov	[next_page], edx     ; yes
  2880                              <1> dap_1:
  2881 00003127 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2882                              <1> 				     ; set relevant bit to 1.
  2883                              <1> 				     ; set CF to the previous bit value	
  2884                              <1> 	;cmc			     ; complement carry flag	
  2885                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2886                              <1> 				     ; if the page is already deallocated
  2887                              <1> 				     ; before.	
  2888 0000312A FF05[306C0000]      <1>         inc     dword [free_pages]
  2889                              <1> dap_2:
  2890 00003130 5A                  <1> 	pop	edx
  2891 00003131 5B                  <1> 	pop	ebx
  2892 00003132 C3                  <1> 	retn
  2893                              <1> 
  2894                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2895                              <1> ;;                                                              ;;
  2896                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2897                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2898                              <1> ;;                                                              ;;
  2899                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2900                              <1> 
  2901                              <1> ;;$Revision: 5057 $
  2902                              <1> 
  2903                              <1> 
  2904                              <1> ;;align 4
  2905                              <1> ;;proc alloc_page
  2906                              <1> 
  2907                              <1> ;;        pushfd
  2908                              <1> ;;        cli
  2909                              <1> ;;        push    ebx
  2910                              <1> ;;;//-
  2911                              <1> ;;        cmp     [pg_data.pages_free], 1
  2912                              <1> ;;        jle     .out_of_memory
  2913                              <1> ;;;//-
  2914                              <1> ;;
  2915                              <1> ;;        mov     ebx, [page_start]
  2916                              <1> ;;        mov     ecx, [page_end]
  2917                              <1> ;;.l1:
  2918                              <1> ;;        bsf     eax, [ebx];
  2919                              <1> ;;        jnz     .found
  2920                              <1> ;;        add     ebx, 4
  2921                              <1> ;;        cmp     ebx, ecx
  2922                              <1> ;;        jb      .l1
  2923                              <1> ;;        pop     ebx
  2924                              <1> ;;        popfd
  2925                              <1> ;;        xor     eax, eax
  2926                              <1> ;;        ret
  2927                              <1> ;;.found:
  2928                              <1> ;;;//-
  2929                              <1> ;;        dec     [pg_data.pages_free]
  2930                              <1> ;;        jz      .out_of_memory
  2931                              <1> ;;;//-
  2932                              <1> ;;        btr     [ebx], eax
  2933                              <1> ;;        mov     [page_start], ebx
  2934                              <1> ;;        sub     ebx, sys_pgmap
  2935                              <1> ;;        lea     eax, [eax+ebx*8]
  2936                              <1> ;;        shl     eax, 12
  2937                              <1> ;;;//-       dec [pg_data.pages_free]
  2938                              <1> ;;        pop     ebx
  2939                              <1> ;;        popfd
  2940                              <1> ;;        ret
  2941                              <1> ;;;//-
  2942                              <1> ;;.out_of_memory:
  2943                              <1> ;;        mov     [pg_data.pages_free], 1
  2944                              <1> ;;        xor     eax, eax
  2945                              <1> ;;        pop     ebx
  2946                              <1> ;;        popfd
  2947                              <1> ;;        ret
  2948                              <1> ;;;//-
  2949                              <1> ;;endp
  2950                              <1> 
  2951                              <1> duplicate_page_dir:
  2952                              <1> 	; 21/09/2015
  2953                              <1> 	; 31/08/2015
  2954                              <1> 	; 20/07/2015
  2955                              <1> 	; 28/04/2015
  2956                              <1> 	; 27/04/2015
  2957                              <1> 	; 18/04/2015
  2958                              <1> 	; 12/04/2015
  2959                              <1> 	; 18/10/2014
  2960                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  2961                              <1> 	;
  2962                              <1> 	; INPUT -> 
  2963                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  2964                              <1> 	;		    page directory.
  2965                              <1> 	; OUTPUT ->
  2966                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  2967                              <1> 	;	       page directory.
  2968                              <1> 	;	(New page directory with new page table entries.)
  2969                              <1> 	;	(New page tables with read only copies of the parent's
  2970                              <1> 	;	pages.)
  2971                              <1> 	;	EAX = 0 -> Error (CF = 1)
  2972                              <1> 	;
  2973                              <1> 	; Modified Registers -> none (except EAX)
  2974                              <1> 	;
  2975 00003133 E802FEFFFF          <1> 	call	allocate_page
  2976 00003138 723E                <1> 	jc	short dpd_err
  2977                              <1> 	;
  2978 0000313A 55                  <1> 	push	ebp ; 20/07/2015
  2979 0000313B 56                  <1> 	push	esi
  2980 0000313C 57                  <1> 	push	edi
  2981 0000313D 53                  <1> 	push	ebx
  2982 0000313E 51                  <1> 	push	ecx
  2983 0000313F 8B35[61700000]      <1> 	mov	esi, [u.pgdir]
  2984 00003145 89C7                <1> 	mov	edi, eax
  2985 00003147 50                  <1> 	push	eax ; save child's page directory address
  2986                              <1> 	; 31/08/2015
  2987                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  2988                              <1> 	; (use same system space for all user page tables) 
  2989 00003148 A5                  <1> 	movsd
  2990 00003149 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  2991 0000314E B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  2992                              <1> dpd_0:	
  2993 00003153 AD                  <1> 	lodsd
  2994                              <1> 	;or	eax, eax
  2995                              <1>         ;jnz     short dpd_1
  2996 00003154 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  2997 00003156 7508                <1> 	jnz	short dpd_1
  2998                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  2999 00003158 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3000 0000315E EB0F                <1> 	jmp	short dpd_2
  3001                              <1> dpd_1:	
  3002 00003160 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3003 00003164 89C3                <1> 	mov	ebx, eax
  3004                              <1> 	; EBX = Parent's page table address
  3005 00003166 E81F000000          <1> 	call	duplicate_page_table
  3006 0000316B 720C                <1> 	jc	short dpd_p_err
  3007                              <1> 	; EAX = Child's page table address
  3008 0000316D 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3009                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3010                              <1> 			 ; (present, writable, user)
  3011                              <1> dpd_2:
  3012 0000316F AB                  <1> 	stosd
  3013 00003170 E2E1                <1> 	loop	dpd_0
  3014                              <1> 	;
  3015 00003172 58                  <1> 	pop	eax  ; restore child's page directory address
  3016                              <1> dpd_3:
  3017 00003173 59                  <1> 	pop	ecx
  3018 00003174 5B                  <1> 	pop	ebx
  3019 00003175 5F                  <1> 	pop	edi
  3020 00003176 5E                  <1> 	pop	esi
  3021 00003177 5D                  <1> 	pop	ebp ; 20/07/2015
  3022                              <1> dpd_err:
  3023 00003178 C3                  <1> 	retn
  3024                              <1> dpd_p_err:
  3025                              <1> 	; release the allocated pages missing (recover free space)
  3026 00003179 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3027 0000317A 8B1D[61700000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3028 00003180 E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3029 00003185 29C0                <1> 	sub	eax, eax ; 0
  3030 00003187 F9                  <1> 	stc
  3031 00003188 EBE9                <1> 	jmp	short dpd_3	
  3032                              <1> 
  3033                              <1> duplicate_page_table:
  3034                              <1> 	; 31/12/2021
  3035                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3036                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3037                              <1> 	; 21/09/2015
  3038                              <1> 	; 20/07/2015
  3039                              <1> 	; 05/05/2015
  3040                              <1> 	; 28/04/2015
  3041                              <1> 	; 27/04/2015
  3042                              <1> 	; 18/04/2015
  3043                              <1> 	; 18/10/2014
  3044                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3045                              <1> 	;
  3046                              <1> 	; INPUT -> 
  3047                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3048                              <1> 	;       20/02/2017		 
  3049                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3050                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3051                              <1> 	; OUTPUT ->
  3052                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3053                              <1> 	;	      (with 'read only' attribute of page table entries)
  3054                              <1> 	;	20/02/2017
  3055                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3056                              <1> 	;	
  3057                              <1> 	;	CF = 1 -> error 
  3058                              <1> 	;
  3059                              <1> 	; Modified Registers -> EBP (except EAX)
  3060                              <1> 	;
  3061 0000318A E8ABFDFFFF          <1> 	call	allocate_page
  3062 0000318F 725B                <1> 	jc	short dpt_err
  3063                              <1> 	;
  3064 00003191 50                  <1> 	push	eax ; *
  3065 00003192 56                  <1> 	push	esi
  3066 00003193 57                  <1> 	push	edi
  3067 00003194 52                  <1> 	push	edx
  3068 00003195 51                  <1> 	push	ecx
  3069                              <1> 	;
  3070 00003196 89DE                <1> 	mov	esi, ebx
  3071 00003198 89C7                <1> 	mov	edi, eax
  3072 0000319A 89C2                <1> 	mov	edx, eax
  3073 0000319C 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3074                              <1> dpt_0:
  3075 000031A2 AD                  <1> 	lodsd
  3076 000031A3 21C0                <1> 	and	eax, eax
  3077 000031A5 7435                <1> 	jz	short dpt_3
  3078 000031A7 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3079                              <1> 	; 24/12/2021
  3080 000031A9 7503                <1> 	jnz	short dpt_1
  3081                              <1> 	;jz	short dpt_p_err
  3082                              <1> 	; 31/12/2021
  3083 000031AB F9                  <1> 	stc
  3084 000031AC EB39                <1> 	jmp	short dpt_p_err
  3085                              <1> 
  3086                              <1> ; 24/12/2021
  3087                              <1> ; ('reload_page' procedure call is disabled)
  3088                              <1> ;
  3089                              <1> ;	; 20/07/2015
  3090                              <1> ;	; ebp = virtual (linear) address of the memory page
  3091                              <1> ;	call	reload_page ; 28/04/2015
  3092                              <1> ;	jc	short dpt_p_err
  3093                              <1> dpt_1:
  3094                              <1> 	; 21/09/2015
  3095 000031AE 89C1                <1> 	mov	ecx, eax
  3096 000031B0 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3097 000031B4 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3098 000031B7 751A                <1> 	jnz	short dpt_2
  3099                              <1> 	; Read only (parent) page
  3100                              <1> 	; 	- there is a third process which uses this page -
  3101                              <1> 	; Allocate a new page for the child process
  3102 000031B9 E87CFDFFFF          <1> 	call	allocate_page
  3103 000031BE 7227                <1> 	jc	short dpt_p_err
  3104 000031C0 57                  <1> 	push	edi
  3105 000031C1 56                  <1> 	push	esi
  3106 000031C2 89CE                <1> 	mov	esi, ecx
  3107 000031C4 89C7                <1> 	mov	edi, eax
  3108 000031C6 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3109 000031CB F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3110 000031CD 5E                  <1> 	pop	esi
  3111 000031CE 5F                  <1> 	pop	edi
  3112                              <1> 	;
  3113                              <1> 
  3114                              <1> ; 24/12/2021
  3115                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3116                              <1> ; 
  3117                              <1> ;	push	ebx
  3118                              <1> ;	push	eax
  3119                              <1> ;	; 20/07/2015
  3120                              <1> ;	mov	ebx, ebp
  3121                              <1> ;	; ebx = virtual (linear) address of the memory page
  3122                              <1> ;	call	add_to_swap_queue
  3123                              <1> ;	pop	eax
  3124                              <1> ;	pop	ebx
  3125                              <1> 
  3126                              <1> 	; 21/09/2015
  3127 000031CF 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3128                              <1> 		; user + writable + present page
  3129 000031D1 EB09                <1> 	jmp	short dpt_3
  3130                              <1> dpt_2:
  3131                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3132 000031D3 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3133                              <1> 		    ; (read only page!)
  3134 000031D5 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3135 000031D8 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3136                              <1> dpt_3:
  3137 000031DC AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3138                              <1> 	;
  3139 000031DD 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3140                              <1> 	;
  3141 000031E3 39D7                <1> 	cmp	edi, edx
  3142 000031E5 72BB                <1> 	jb	short dpt_0
  3143                              <1> dpt_p_err:
  3144 000031E7 59                  <1> 	pop	ecx
  3145 000031E8 5A                  <1> 	pop	edx
  3146 000031E9 5F                  <1> 	pop	edi
  3147 000031EA 5E                  <1> 	pop	esi
  3148 000031EB 58                  <1> 	pop	eax ; *
  3149                              <1> dpt_err:
  3150 000031EC C3                  <1> 	retn
  3151                              <1> 
  3152                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3153                              <1> 	; 31/12/2021
  3154                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3155                              <1> 	; 21/09/2015
  3156                              <1> 	; 19/09/2015
  3157                              <1> 	; 17/09/2015
  3158                              <1> 	; 28/08/2015
  3159                              <1> 	; 20/07/2015
  3160                              <1> 	; 28/06/2015
  3161                              <1> 	; 03/05/2015
  3162                              <1> 	; 30/04/2015
  3163                              <1> 	; 18/04/2015
  3164                              <1> 	; 12/04/2015
  3165                              <1> 	; 30/10/2014
  3166                              <1> 	; 11/09/2014
  3167                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3168                              <1> 	;
  3169                              <1> 	; Note: This is not an interrupt/exception handler.
  3170                              <1> 	;	This is a 'page fault remedy' subroutine 
  3171                              <1> 	;	which will be called by standard/uniform
  3172                              <1> 	;	exception handler.
  3173                              <1> 	;
  3174                              <1> 	; INPUT -> 
  3175                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3176                              <1> 	;
  3177                              <1> 	;	cr2 = the virtual (linear) address 
  3178                              <1> 	;	      which has caused to page fault (19/09/2015)
  3179                              <1> 	;
  3180                              <1> 	; OUTPUT ->
  3181                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3182                              <1> 	;	EAX = 0 -> no error
  3183                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3184                              <1> 	;
  3185                              <1> 	; Modified Registers -> none (except EAX)
  3186                              <1> 	;	
  3187                              <1>         ;
  3188                              <1>         ; ERROR CODE:
  3189                              <1> 	;	 31  .....	4   3	2   1	0
  3190                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3191                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3192                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3193                              <1> 	;
  3194                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3195                              <1>     	;		a page-protection violation. When not set,
  3196                              <1> 	;		it was caused by a non-present page.
  3197                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3198                              <1> 	;		a page write. When not set, it was caused
  3199                              <1> 	;		by a page read.
  3200                              <1> 	; U : USER    -	When set, the page fault was caused 
  3201                              <1> 	;		while CPL = 3. 
  3202                              <1> 	;		This does not necessarily mean that
  3203                              <1> 	;		the page fault was a privilege violation.
  3204                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3205                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3206                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3207                              <1> 	;     FETCH	an instruction fetch
  3208                              <1> 	;
  3209                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3210                              <1> 	;  31               22                  12 11                    0
  3211                              <1> 	; +-------------------+-------------------+-----------------------+
  3212                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3213                              <1>        	; +-------------------+-------------------+-----------------------+
  3214                              <1> 	;
  3215                              <1> 
  3216                              <1> 	;; CR3 REGISTER (Control Register 3)
  3217                              <1> 	;  31                                   12             5 4 3 2   0
  3218                              <1> 	; +---------------------------------------+-------------+---+-----+
  3219                              <1>       	; |                                       |  		|P|P|     |
  3220                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3221                              <1>       	; |                                       | 		|D|T|     |
  3222                              <1>    	; +---------------------------------------+-------------+---+-----+
  3223                              <1> 	;
  3224                              <1> 	;	PWT    - WRITE THROUGH
  3225                              <1> 	;	PCD    - CACHE DISABLE		
  3226                              <1> 	;
  3227                              <1> 	;
  3228                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3229                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3230                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3231                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3232                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3233                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3234                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3235                              <1> 	;
  3236                              <1>         ;       P      - PRESENT
  3237                              <1>         ;       R/W    - READ/WRITE
  3238                              <1>         ;       U/S    - USER/SUPERVISOR
  3239                              <1> 	;	PWT    - WRITE THROUGH
  3240                              <1> 	;	PCD    - CACHE DISABLE	
  3241                              <1> 	;	A      - ACCESSED	
  3242                              <1>         ;       D      - DIRTY (IGNORED)
  3243                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3244                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3245                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3246                              <1> 	;
  3247                              <1> 	;
  3248                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3249                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3250                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3251                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3252                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3253                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3254                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3255                              <1> 	;
  3256                              <1>         ;       P      - PRESENT
  3257                              <1>         ;       R/W    - READ/WRITE
  3258                              <1>         ;       U/S    - USER/SUPERVISOR
  3259                              <1> 	;	PWT    - WRITE THROUGH
  3260                              <1> 	;	PCD    - CACHE DISABLE	
  3261                              <1> 	;	A      - ACCESSED	
  3262                              <1>         ;       D      - DIRTY
  3263                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3264                              <1> 	;	G      - GLOBAL	 
  3265                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3266                              <1> 	;
  3267                              <1> 	;
  3268                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3269                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3270                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3271                              <1>       	; |                                       |     | | | | | | |U|R| |
  3272                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3273                              <1>       	; |                                       |     | | | | | | |S|W| |
  3274                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3275                              <1> 	;
  3276                              <1>         ;       P      - PRESENT
  3277                              <1>         ;       R/W    - READ/WRITE
  3278                              <1>         ;       U/S    - USER/SUPERVISOR
  3279                              <1>         ;       D      - DIRTY
  3280                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3281                              <1> 	;
  3282                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3283                              <1> 	;
  3284                              <1> 	;
  3285                              <1> 	;; Invalid Page Table Entry
  3286                              <1> 	; 31                                                           1 0
  3287                              <1>       	; +-------------------------------------------------------------+-+
  3288                              <1>       	; |                                                             | |
  3289                              <1>       	; |                          AVAILABLE                          |0|
  3290                              <1>       	; |                                                             | |
  3291                              <1>       	; +-------------------------------------------------------------+-+
  3292                              <1> 	;
  3293                              <1> 
  3294 000031ED 53                  <1> 	push	ebx
  3295 000031EE 52                  <1> 	push	edx
  3296 000031EF 51                  <1> 	push	ecx
  3297                              <1> 	;
  3298                              <1> 	; 21/09/2015 (debugging)
  3299 000031F0 FF05[71700000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3300 000031F6 FF05[D8800000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3301                              <1> 	; 28/06/2015
  3302                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3303 000031FC 8A15[D0800000]      <1> 	mov	dl, [error_code]
  3304                              <1> 	;
  3305 00003202 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3306                              <1> 			; sign
  3307 00003205 7425                <1> 	jz	short pfh_alloc_np
  3308                              <1> 	; 
  3309                              <1> 	; If it is not a 'write on read only page' type page fault
  3310                              <1> 	; major page fault error with minor reason must be returned without 
  3311                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3312                              <1> 	; after return here!
  3313                              <1> 	; Page fault will be remedied, by copying page contents
  3314                              <1> 	; to newly allocated page with write permission;
  3315                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3316                              <1> 	; used for working with minimum possible memory usage. 
  3317                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3318                              <1> 	; process with 'read only' flag. If the child process attempts to
  3319                              <1> 	; write on these read only pages, page fault will be directed here
  3320                              <1> 	; for allocating a new page with same data/content. 
  3321                              <1> 	;
  3322                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3323                              <1> 	; will not force to separate CODE and DATA space 
  3324                              <1> 	; in a process/program... 
  3325                              <1> 	; CODE segment/section may contain DATA!
  3326                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3327                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3328                              <1> 	;	
  3329 00003207 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3330                              <1> 			; sign
  3331 0000320A 7418                <1>         jz      pfh_p_err
  3332                              <1> 	; 31/08/2015
  3333 0000320C F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3334                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3335 0000320F 7413                <1>         jz	short pfh_pv_err
  3336                              <1> 	;
  3337                              <1> 	; make a new page and copy the parent's page content
  3338                              <1> 	; as the child's new page content
  3339                              <1> 	;
  3340 00003211 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3341                              <1> 			 ; which has caused to page fault
  3342 00003214 E87C000000          <1> 	call 	copy_page
  3343 00003219 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3344                              <1> 	;
  3345 0000321B EB72                <1>         jmp     pfh_cpp_ok
  3346                              <1> 
  3347                              <1> 	; 31/12/2021 (short jump)
  3348                              <1> pfh_im_err:
  3349 0000321D B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3350                              <1> 			; Major (Primary) Error: Page Fault
  3351                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3352 00003222 EB6D                <1> 	jmp	short pfh_err_retn
  3353                              <1> 
  3354                              <1> 	; 31/12/2021
  3355                              <1> pfh_p_err: ; 09/03/2015
  3356                              <1> pfh_pv_err:
  3357                              <1> 	; Page fault was caused by a protection-violation
  3358 00003224 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3359                              <1> 			; Major (Primary) Error: Page Fault
  3360                              <1> 			; Minor (Secondary) Error: Protection violation !
  3361 00003229 F9                  <1> 	stc
  3362 0000322A EB65                <1> 	jmp	short pfh_err_retn
  3363                              <1> 	
  3364                              <1> pfh_alloc_np:
  3365 0000322C E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3366 00003231 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3367                              <1> pfh_chk_cpl:
  3368                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3369                              <1> 		; (Lower 12 bits are ZERO, because 
  3370                              <1> 		;	the address is on a page boundary)
  3371 00003233 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3372 00003236 7505                <1> 	jnz	short pfh_um
  3373                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3374 00003238 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3375                              <1> 			 ; of the current/active page directory
  3376                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3377                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3378 0000323B EB06                <1> 	jmp	short pfh_get_pde
  3379                              <1> 	;
  3380                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3381 0000323D 8B1D[61700000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3382                              <1> 			; Physical address of the USER's page directory
  3383                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3384                              <1> pfh_get_pde:
  3385 00003243 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3386 00003246 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3387                              <1> 			 ; which has been caused to page fault
  3388                              <1> 			 ;
  3389 00003249 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3390 0000324C 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3391                              <1> 	;
  3392 0000324F 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3393 00003251 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3394 00003253 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3395 00003256 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3396                              <1> 			  	  ; set/validate page directory entry
  3397 00003258 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3398 0000325D 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3399 0000325F 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3400 00003261 EB16                <1> 	jmp	short pfh_get_pte
  3401                              <1> pfh_set_pde:
  3402                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3403                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3404                              <1> 	;
  3405 00003263 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3406 00003265 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3407 00003267 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3408 00003269 89C3                <1> 	mov	ebx, eax
  3409 0000326B E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3410 00003270 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3411                              <1> pfh_spde_1:
  3412                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3413 00003272 89C1                <1> 	mov	ecx, eax
  3414 00003274 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3415                              <1> pfh_get_pte:
  3416 00003279 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3417                              <1> 			 ; which has been caused to page fault
  3418 0000327C 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3419 0000327E C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3420                              <1> 			 ; higher 20 bits of the page fault address 
  3421 00003281 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3422 00003286 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3423 00003289 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3424                              <1> ; 24/12/2021
  3425                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3426                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3427                              <1> ; 24/12/2021
  3428                              <1> ; ('swap_in' procedure call has been disabled)
  3429                              <1> ;
  3430                              <1> ;	and	eax, eax
  3431                              <1> ;	jz	short pfh_gpte_1
  3432                              <1> ;	; 20/07/2015
  3433                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3434                              <1> ;	push	ebp ; 20/07/2015
  3435                              <1> ;	mov	ebp, cr2
  3436                              <1> ;		; ECX = physical address of the page table entry
  3437                              <1> ;		; EBX = Memory page address (physical!)
  3438                              <1> ;		; EAX = Swap disk (offset) address
  3439                              <1> ;		; EBP = virtual address (page fault address)
  3440                              <1> ;	call	swap_in
  3441                              <1> ;	pop	ebp
  3442                              <1> ;	jc      short pfh_err_retn
  3443                              <1> ;	xchg	ecx, ebx
  3444                              <1> ;		; EBX = physical address of the page table entry
  3445                              <1> ;		; ECX = new page
  3446                              <1> pfh_gpte_1:
  3447 0000328B 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3448 0000328D 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3449                              <1> pfh_cpp_ok:
  3450                              <1> ; 24/12/2021
  3451                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3452                              <1> ;
  3453                              <1> ;	; 20/07/2015
  3454                              <1> ;	mov	ebx, cr2
  3455                              <1> ;	call 	add_to_swap_queue
  3456                              <1> 	;
  3457                              <1> 	; The new PTE (which contains the new page) will be added to 
  3458                              <1> 	; the swap queue, here. 
  3459                              <1> 	; (Later, if memory will become insufficient, 
  3460                              <1> 	; one page will be swapped out which is at the head of 
  3461                              <1> 	; the swap queue by using FIFO and access check methods.)
  3462                              <1> 	;
  3463 0000328F 31C0                <1> 	xor	eax, eax  ; 0
  3464                              <1> 	;
  3465                              <1> pfh_err_retn:
  3466 00003291 59                  <1> 	pop	ecx
  3467 00003292 5A                  <1> 	pop	edx
  3468 00003293 5B                  <1> 	pop	ebx
  3469 00003294 C3                  <1> 	retn 
  3470                              <1> 	
  3471                              <1> copy_page:
  3472                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3473                              <1> 	; 16/04/2021
  3474                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3475                              <1> 	; 22/09/2015
  3476                              <1> 	; 21/09/2015
  3477                              <1> 	; 19/09/2015
  3478                              <1> 	; 07/09/2015
  3479                              <1> 	; 31/08/2015
  3480                              <1> 	; 20/07/2015
  3481                              <1> 	; 05/05/2015
  3482                              <1> 	; 03/05/2015
  3483                              <1> 	; 18/04/2015
  3484                              <1> 	; 12/04/2015
  3485                              <1> 	; 30/10/2014
  3486                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3487                              <1> 	;
  3488                              <1> 	; INPUT -> 
  3489                              <1> 	;	EBX = Virtual (linear) address of source page
  3490                              <1> 	;	     (Page fault address)
  3491                              <1> 	; OUTPUT ->
  3492                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3493                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3494                              <1> 	;	EAX = 0 (CF = 1) 
  3495                              <1> 	;		if there is not a free page to be allocated
  3496                              <1> 	;	(page content of the source page will be copied
  3497                              <1> 	;	onto the target/new page) 	
  3498                              <1> 	;
  3499                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3500                              <1> 	;
  3501                              <1> 
  3502                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3503                              <1> 	; INPUT: 
  3504                              <1> 	;	EBX = Virtual (linear) address of source page
  3505                              <1> 	;	     (Page fault address)
  3506                              <1> 	; OUTPUT:
  3507                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3508                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3509                              <1> 	;	EAX = 0 (CF = 1) 
  3510                              <1> 	;		if there is not a free page to be allocated
  3511                              <1> 	;	(page content of the source page will be copied
  3512                              <1> 	;	onto the target/new page) 	
  3513                              <1> 	;
  3514                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3515                              <1> 	
  3516 00003295 56                  <1> 	push	esi ; *
  3517 00003296 57                  <1> 	push	edi ; **
  3518                              <1> 	; 16/04/2021
  3519                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3520                              <1> 	;push	ebx ; ***
  3521                              <1> 	;push	ecx ; ****
  3522 00003297 31F6                <1> 	xor 	esi, esi
  3523 00003299 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3524 0000329C 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3525 0000329E C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3526 000032A1 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3527 000032A4 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3528 000032A6 031D[61700000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3529 000032AC 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3530 000032AE 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3531 000032B2 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3532 000032B4 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3533 000032BA 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3534 000032BE 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3535                              <1> 	; 07/09/2015
  3536 000032C0 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3537                              <1> 				     ; read only page as a child process?)	
  3538 000032C5 7509                <1> 	jnz	short cpp_0 ; yes
  3539 000032C7 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3540 000032C9 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3541 000032CE EB32                <1> 	jmp	short cpp_1
  3542                              <1> cpp_0:
  3543 000032D0 89FE                <1> 	mov	esi, edi
  3544 000032D2 0335[65700000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3545 000032D8 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3546 000032DA 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3547 000032DE 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3548 000032E0 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3549 000032E6 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3550 000032EA 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3551 000032EC 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3552                              <1> 	; 21/09/2015
  3553 000032EE 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3554 000032F0 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3555                              <1> 	;
  3556 000032F4 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3557 000032F7 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3558                              <1> 	;
  3559 000032F9 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3560 000032FE 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3561 00003300 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3562                              <1> 			    ; Convert child's page to writable page
  3563                              <1> cpp_1:
  3564 00003302 E833FCFFFF          <1> 	call	allocate_page
  3565 00003307 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3566 00003309 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3567 0000330B 7405                <1> 	jz	short cpp_2
  3568                              <1> 		; Convert read only page to writable page 
  3569                              <1> 		;(for the parent of the current process)
  3570                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3571                              <1> 	; 22/09/2015
  3572 0000330D 890E                <1> 	mov	[esi], ecx
  3573 0000330F 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3574                              <1> 				 ; 1+2+4 = 7
  3575                              <1> cpp_2:
  3576 00003312 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3577                              <1> 	; 07/09/2015
  3578 00003314 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3579 00003316 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3580 0000331B F3A5                <1> 	rep	movsd ; 31/08/2015
  3581                              <1> cpp_3:		
  3582 0000331D 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3583 0000331F 8903                <1> 	mov	[ebx], eax ; Update PTE
  3584 00003321 28C0                <1> 	sub	al, al ; clear attributes
  3585                              <1> cpp_4:
  3586                              <1> 	; 16/04/2021
  3587                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3588                              <1> 	;pop	ecx ; ****
  3589                              <1> 	;pop	ebx ; ***
  3590 00003323 5F                  <1> 	pop	edi ; **
  3591 00003324 5E                  <1> 	pop	esi ; *
  3592 00003325 C3                  <1> 	retn
  3593                              <1> 
  3594                              <1> ;; 28/04/2015
  3595                              <1> ;; 24/10/2014
  3596                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3597                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3598                              <1> ;;
  3599                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3600                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3601                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3602                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3603                              <1> ;;
  3604                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3605                              <1> ;;
  3606                              <1> ;; Method:
  3607                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3608                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3609                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3610                              <1> ;;	When a new page is being allocated, swap queue is updated
  3611                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3612                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3613                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3614                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3615                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3616                              <1> ;;	offset value becomes it's previous offset value - 4.
  3617                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3618                              <1> ;;	the queue/list is not shifted.
  3619                              <1> ;;	After the queue/list shift, newly allocated page is added
  3620                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3621                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3622                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3623                              <1> ;;	
  3624                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3625                              <1> ;;	the first non-accessed, writable page in the list, 
  3626                              <1> ;;	from the head to the tail. The list is shifted to left 
  3627                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3628                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3629                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3630                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3631                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3632                              <1> ;;	procedure will be failed)...
  3633                              <1> ;;
  3634                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3635                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3636                              <1> ;;	(PTE) will be added to the tail of the queue after
  3637                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3638                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3639                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3640                              <1> ;;
  3641                              <1> ;;
  3642                              <1> ;;	
  3643                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3644                              <1> ;;
  3645                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3646                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3647                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3648                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3649                              <1> ;;
  3650                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3651                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3652                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3653                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3654                              <1> ;; 		 (entire swap space must be accessed by using
  3655                              <1> ;;		 31 bit offset address) 
  3656                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3657                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3658                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3659                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3660                              <1> ;;
  3661                              <1> ;; 					
  3662                              <1> ;; Method:
  3663                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3664                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3665                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3666                              <1> ;;	Swapping out is performed by using swap page queue.
  3667                              <1> ;;
  3668                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3669                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3670                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3671                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3672                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3673                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3674                              <1> ;;	calculated by adding offset value to the swap partition's 
  3675                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3676                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3677                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3678                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3679                              <1> ;;	is in a partitioned virtual hard disk.) 
  3680                              <1> ;;
  3681                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3682                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3683                              <1> ;;
  3684                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3685                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3686                              <1> ;;
  3687                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3688                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3689                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3690                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3691                              <1> ;;	it means relevant (respective) block is in use, and, 
  3692                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3693                              <1> ;;      swap disk/file block is free.
  3694                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3695                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3696                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3697                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3698                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3699                              <1> ;;	------------------------------------------------------------
  3700                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3701                              <1> ;;	------------------------------------------------------------
  3702                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3703                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3704                              <1> ;;
  3705                              <1> ;;	..............................................................
  3706                              <1> ;;
  3707                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3708                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3709                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3710                              <1> ;;	position with value of 1 on the table is converted to swap
  3711                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3712                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3713                              <1> ;;	number of physical swap disk or virtual swap disk)
  3714                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3715                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3716                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3717                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3718                              <1> ;;	If disk write procedure returns with error or free count of 
  3719                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3720                              <1> ;;	'insufficient memory error' (cf=1). 
  3721                              <1> ;;
  3722                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3723                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3724                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3725                              <1> ;;	free blocks after a disk write error. It will return to 
  3726                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3727                              <1> ;;
  3728                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3729                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3730                              <1> ;;	address (cf=0). 
  3731                              <1> ;;
  3732                              <1> ;;	..............................................................
  3733                              <1> ;;
  3734                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3735                              <1> ;;	file sectors at specified memory page. Then page allocation
  3736                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3737                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3738                              <1> ;;	to do, except to terminate the process which is the owner of
  3739                              <1> ;;	the swapped page.
  3740                              <1> ;;
  3741                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3742                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3743                              <1> ;;	updates [swpd_first] pointer if it is required.
  3744                              <1> ;;
  3745                              <1> ;;	..............................................................	 
  3746                              <1> ;;
  3747                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3748                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3749                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3750                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3751                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3752                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3753                              <1> ;;
  3754                              <1> 
  3755                              <1> ; 24/12/2021
  3756                              <1> ; ('swap_in' procedure call is disabled)
  3757                              <1> 
  3758                              <1> ;swap_in:
  3759                              <1> 	; 31/08/2015
  3760                              <1> 	; 20/07/2015
  3761                              <1> 	; 28/04/2015
  3762                              <1> 	; 18/04/2015
  3763                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3764                              <1> 	;
  3765                              <1> 	; INPUT -> 
  3766                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3767                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3768                              <1> 	;	EAX = Offset Address for the swapped page on the
  3769                              <1> 	;	      swap disk or in the swap file.
  3770                              <1> 	;
  3771                              <1> 	; OUTPUT ->
  3772                              <1> 	;	EAX = 0 if loading at memory has been successful
  3773                              <1> 	;
  3774                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3775                              <1> 	;		  or sector not present or drive not ready
  3776                              <1> 	;	     EAX = Error code
  3777                              <1> 	;	     [u.error] = EAX 
  3778                              <1> 	;		       = The last error code for the process
  3779                              <1> 	;		         (will be reset after returning to user)	  
  3780                              <1> 	;
  3781                              <1> 	; Modified Registers -> EAX
  3782                              <1> 	;
  3783                              <1> 
  3784                              <1> ;       cmp     dword [swp_drv], 0
  3785                              <1> ;	jna	short swpin_dnp_err
  3786                              <1> ;
  3787                              <1> ;	cmp	eax, [swpd_size]
  3788                              <1> ;	jnb	short swpin_snp_err
  3789                              <1> ;
  3790                              <1> ;	push	esi
  3791                              <1> ;	push	ebx
  3792                              <1> ;	push	ecx
  3793                              <1> ;	mov	esi, [swp_drv]	
  3794                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3795                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3796                              <1> ;		; size different than 512 bytes, logical disk sector
  3797                              <1> ;		; size is 512 bytes and disk reading procedure
  3798                              <1> ;		; will be performed for reading 4096 bytes
  3799                              <1> ;		; (2*2048, 8*512). 
  3800                              <1> ;	; ESI = Logical disk description table address
  3801                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3802                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3803                              <1> ;	; ECX = Sector count ; 8 sectors
  3804                              <1> ;	push	eax
  3805                              <1> ;	call	logical_disk_read
  3806                              <1> ;	pop	eax
  3807                              <1> ;	jnc	short swpin_read_ok
  3808                              <1> ;	;
  3809                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3810                              <1> ;	mov	[u.error], eax
  3811                              <1> ;	jmp	short swpin_retn
  3812                              <1> ;	;
  3813                              <1> ;swpin_read_ok:
  3814                              <1> ;	; EAX = Offset address (logical sector number)
  3815                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3816                              <1> ;	;
  3817                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3818                              <1> ;	; 20/07/2015
  3819                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3820                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3821                              <1> ;	mov	bl, [u.uno] ; current process number
  3822                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3823                              <1> ;	call	swap_queue_shift
  3824                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3825                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3826                              <1> ;	; zf = 1
  3827                              <1> ;swpin_retn:
  3828                              <1> ;	pop	ecx
  3829                              <1> ;	pop	ebx
  3830                              <1> ;	pop	esi
  3831                              <1> ;	retn
  3832                              <1> ;
  3833                              <1> ;swpin_dnp_err:
  3834                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3835                              <1> ;swpin_err_retn:
  3836                              <1> ;	mov	[u.error], eax
  3837                              <1> ;	stc
  3838                              <1> ;	retn
  3839                              <1> ;
  3840                              <1> ;swpin_snp_err:
  3841                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3842                              <1> ;	jmp	short swpin_err_retn
  3843                              <1> 
  3844                              <1> ; 24/12/2021
  3845                              <1> ; ('swap_out' procedure call is disabled)
  3846                              <1> 
  3847                              <1> ;swap_out:
  3848                              <1> 	; 10/06/2016
  3849                              <1> 	; 07/06/2016
  3850                              <1>         ; 23/05/2016
  3851                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3852                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3853                              <1> 	;
  3854                              <1> 	; INPUT -> 
  3855                              <1> 	;	none
  3856                              <1> 	;
  3857                              <1> 	; OUTPUT ->
  3858                              <1> 	;	EAX = Physical page address (which is swapped out
  3859                              <1> 	;	      for allocating a new page)
  3860                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3861                              <1> 	;		  or sector not present or drive not ready
  3862                              <1> 	;	     EAX = Error code
  3863                              <1> 	;	     [u.error] = EAX 
  3864                              <1> 	;		       = The last error code for the process
  3865                              <1> 	;		         (will be reset after returning to user)	  
  3866                              <1> 	;
  3867                              <1> 	; Modified Registers -> none (except EAX)
  3868                              <1> 	;
  3869                              <1> 
  3870                              <1> ;	cmp 	word [swpq_count], 1
  3871                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3872                              <1> ;
  3873                              <1> ;       ;cmp    dword [swp_drv], 1
  3874                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3875                              <1> ;
  3876                              <1> ;       cmp     dword [swpd_free], 1
  3877                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3878                              <1> ;
  3879                              <1> ;	push	ebx ; *
  3880                              <1> ;swpout_1:
  3881                              <1> ;	; 10/06/2016
  3882                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3883                              <1> ;	call	swap_queue_shift
  3884                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3885                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3886                              <1> ;				       ; pointer in the swap queue
  3887                              <1> ;	; EAX = PTE value of the page
  3888                              <1> ;	; EBX = PTE address of the page
  3889                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3890                              <1> ;	;
  3891                              <1> ;	; 07/06/2016
  3892                              <1> ;	; 19/05/2016
  3893                              <1> ;	; check this page is in timer events or not
  3894                              <1> ;	
  3895                              <1> ;swpout_timer_page_0:
  3896                              <1> ;	push	edx ; **
  3897                              <1> ;
  3898                              <1> ;	; 07/06/2016
  3899                              <1> ;	cmp	byte [timer_events], 0 
  3900                              <1> ;	jna	short swpout_2
  3901                              <1> ;	;
  3902                              <1> ;	mov	dl, [timer_events]
  3903                              <1> ;
  3904                              <1> ;	push	ecx ; ***
  3905                              <1> ;	push	ebx ; ****
  3906                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3907                              <1> ;			       ; structures 
  3908                              <1> ;swpout_timer_page_1:
  3909                              <1> ;	mov	cl, [ebx]
  3910                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3911                              <1> ;	jz	short swpout_timer_page_3
  3912                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3913                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3914                              <1> ;				; of the response byte address, to
  3915                              <1> ;				; get beginning of the page address)
  3916                              <1> ;	cmp	eax, ecx
  3917                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3918                              <1> ;	
  3919                              <1> ;	; !same page!
  3920                              <1> ;	;
  3921                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3922                              <1> ;	; This page will be used by the kernel to put timer event
  3923                              <1> ;	; response (signal return) byte at the requested address;
  3924                              <1> ;	; in order to prevent a possible wrong write (while
  3925                              <1> ;	; this page is swapped out) on physical memory,
  3926                              <1> ;	; we must protect this page against to be swapped out!
  3927                              <1> ;	;
  3928                              <1> ;	pop	ebx ; ****
  3929                              <1> ;	pop	ecx ; ***
  3930                              <1> ;	pop	edx ; **
  3931                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3932                              <1> ; 
  3933                              <1> ;swpout_timer_page_2:
  3934                              <1> ;	; 07/06/2016
  3935                              <1> ;	dec	dl
  3936                              <1> ;	jz	short swpout_timer_page_4
  3937                              <1> ;swpout_timer_page_3:
  3938                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3939                              <1> ;	;jnb	short swpout_timer_page_4
  3940                              <1> ;	add	ebx, 16
  3941                              <1> ;	jmp	short swpout_timer_page_1	
  3942                              <1> ;
  3943                              <1> ;swpout_timer_page_4:
  3944                              <1> ;	pop	ebx ; ****
  3945                              <1> ;	pop	ecx ; ***
  3946                              <1> ;swpout_2:
  3947                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  3948                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  3949                              <1> ;	;
  3950                              <1> ;	call	link_swap_block
  3951                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  3952                              <1> ;				       ; because [swpd_free] value
  3953                              <1> ;				       ; was checked at the beginging. 	
  3954                              <1> ;	pop	edx ; **
  3955                              <1> ;	pop	ebx ; *
  3956                              <1> ;	jmp	short swpout_nfspc_err 
  3957                              <1> ;swpout_3:
  3958                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  3959                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  3960                              <1> ;	;	
  3961                              <1> ;	push	esi ; **
  3962                              <1> ;	push	ecx ; ***
  3963                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  3964                              <1> ;	mov	esi, [swp_drv]	
  3965                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3966                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3967                              <1> ;		; size different than 512 bytes, logical disk sector
  3968                              <1> ;		; size is 512 bytes and disk writing procedure
  3969                              <1> ;		; will be performed for writing 4096 bytes
  3970                              <1> ;		; (2*2048, 8*512). 
  3971                              <1> ;	; ESI = Logical disk description table address
  3972                              <1> ;	; EBX = Buffer (Page) address
  3973                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3974                              <1> ;	; ECX = Sector count ; 8 sectors
  3975                              <1> ;	; edx = PTE address
  3976                              <1> ;	call	logical_disk_write
  3977                              <1> ;	; edx = PTE address
  3978                              <1> ;	pop	ecx ; sector address	
  3979                              <1> ;	jnc	short swpout_write_ok
  3980                              <1> ;	;
  3981                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  3982                              <1> ;swpout_dw_err:
  3983                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  3984                              <1> ;	mov	[u.error], eax
  3985                              <1> ;	jmp	short swpout_retn
  3986                              <1> ;	;
  3987                              <1> ;swpout_write_ok:
  3988                              <1> ;	; EBX = Buffer (page) address
  3989                              <1> ;	; EDX = Page Table Entry address
  3990                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  3991                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  3992                              <1> ;	mov 	[edx], ecx 
  3993                              <1> ;		; bit 0 = 0 (swapped page)
  3994                              <1> ;	mov	eax, ebx
  3995                              <1> ;swpout_retn:
  3996                              <1> ;	pop	ecx ; ***
  3997                              <1> ;	pop	esi ; **
  3998                              <1> ;	pop	ebx ; *
  3999                              <1> ;	retn
  4000                              <1> ;
  4001                              <1> ;;swpout_dnp_err:
  4002                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4003                              <1> ;;	jmp	short swpout_err_retn
  4004                              <1> ;swpout_nfspc_err:
  4005                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4006                              <1> ;swpout_err_retn:
  4007                              <1> ;	mov	[u.error], eax
  4008                              <1> ;	;stc
  4009                              <1> ;	retn
  4010                              <1> ;swpout_npts_err:
  4011                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4012                              <1> ;	pop	ebx
  4013                              <1> ;	jmp	short swpout_err_retn
  4014                              <1> ;swpout_im_err:
  4015                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4016                              <1> ;	jmp	short swpout_err_retn
  4017                              <1> 
  4018                              <1> ; 24/12/2021
  4019                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4020                              <1> 
  4021                              <1> ;swap_queue_shift:
  4022                              <1> 	; 26/03/2017
  4023                              <1> 	; 10/06/2016
  4024                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4025                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4026                              <1> 	;
  4027                              <1> 	; INPUT ->
  4028                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4029                              <1> 	;	      and process number combination (bit 0 to 11)
  4030                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4031                              <1> 	;	
  4032                              <1> 	; OUTPUT ->
  4033                              <1> 	;	If EBX input > 0 
  4034                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4035                              <1> 	; 	   from the tail to the head, up to entry offset
  4036                              <1> 	; 	   which points to EBX input value or nothing
  4037                              <1> 	;	   to do if EBX value is not found on the queue.
  4038                              <1> 	;	   (The entry -with EBX value- will be removed
  4039                              <1> 	;	   from the queue if it is found.)
  4040                              <1> 	;
  4041                              <1> 	;	   EAX = 0		
  4042                              <1> 	;
  4043                              <1> 	;	If EBX input = 0
  4044                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4045                              <1> 	; 	   from the tail to the head, if the PTE address
  4046                              <1> 	;	   which is pointed in head of the queue is marked
  4047                              <1> 	;	   as "accessed" or it is marked as "non present".
  4048                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4049                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4050                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4051                              <1> 	;	   -without dropping pointer of the PTE from 
  4052                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4053                              <1> 	;	   Pointer in the head will be moved into the tail,
  4054                              <1> 	;	   other PTEs will be shifted on head direction.)
  4055                              <1> 	;
  4056                              <1> 	;	   Swap queue will be shifted up to the first
  4057                              <1> 	;	   'present' or 'non accessed' page will be found
  4058                              <1> 	;	   (as pointed) on the queue head (then it will be
  4059                              <1>         ;          removed/dropped from the queue).
  4060                              <1> 	;
  4061                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4062                              <1> 	;		 (it's pointer -virtual address-) dropped
  4063                              <1> 	;		 (removed) from swap queue.
  4064                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4065                              <1> 	;	         which is (it's pointer -virtual address-)
  4066                              <1> 	;		 dropped (removed) from swap queue.
  4067                              <1> 	;
  4068                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4069                              <1> 	;
  4070                              <1> 	; Modified Registers -> EAX, EBX
  4071                              <1> 	;
  4072                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4073                              <1> ;	and	ax, ax
  4074                              <1> ;	jz	short swpqs_retn
  4075                              <1> ;	push	edi
  4076                              <1> ;	push	esi
  4077                              <1> ;	push	ecx
  4078                              <1> ;	mov	esi, swap_queue
  4079                              <1> ;	mov	ecx, eax
  4080                              <1> ;	or	ebx, ebx
  4081                              <1> ;	jz	short swpqs_7
  4082                              <1> ;swpqs_1:
  4083                              <1> ;	lodsd
  4084                              <1> ;	cmp	eax, ebx
  4085                              <1> ;	je	short swpqs_2
  4086                              <1> ;	loop	swpqs_1
  4087                              <1> ;	; 10/06/2016
  4088                              <1> ;	sub	eax, eax 
  4089                              <1> ;	jmp	short swpqs_6
  4090                              <1> ;swpqs_2:
  4091                              <1> ;	mov	edi, esi
  4092                              <1> ;	sub 	edi, 4
  4093                              <1> ;swpqs_3:
  4094                              <1> ;	dec	word [swpq_count]
  4095                              <1> ;	jz	short swpqs_5
  4096                              <1> ;swpqs_4:
  4097                              <1> ;	dec 	ecx
  4098                              <1> ;	rep	movsd	; shift up (to the head)
  4099                              <1> ;swpqs_5:
  4100                              <1> ;	xor	eax, eax
  4101                              <1> ;	mov	[edi], eax
  4102                              <1> ;swpqs_6:
  4103                              <1> ;	pop	ecx
  4104                              <1> ;	pop	esi
  4105                              <1> ;	pop	edi
  4106                              <1> ;swpqs_retn:
  4107                              <1> ;	retn		
  4108                              <1> ;swpqs_7:
  4109                              <1> ;	mov	edi, esi ; head
  4110                              <1> ;	lodsd
  4111                              <1> ;	; 20/07/2015
  4112                              <1> ;	mov	ebx, eax
  4113                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4114                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4115                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4116                              <1> ;		      ; ax = process number (1 to 4095)
  4117                              <1> ;	cmp	al, [u.uno]
  4118                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4119                              <1> ;	jne	short swpqs_8
  4120                              <1> ;	mov	eax, [u.pgdir]
  4121                              <1> ;	jmp	short swpqs_9
  4122                              <1> ;swpqs_8:
  4123                              <1> ;	; 09/06/2016
  4124                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4125                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4126                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4127                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4128                              <1> ;
  4129                              <1> ;	;shl	ax, 2
  4130                              <1> ;	shl	al, 2
  4131                              <1> ;	mov 	eax, [eax+p.upage-4]
  4132                              <1> ;	or	eax, eax
  4133                              <1> ;	jz	short swpqs_3 ; invalid upage
  4134                              <1> ;	add	eax, u.pgdir - user
  4135                              <1> ;			 ; u.pgdir value for the process
  4136                              <1> ;			 ; is in [eax]
  4137                              <1> ;	mov	eax, [eax]
  4138                              <1> ;	and	eax, eax
  4139                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4140                              <1> ;swpqs_9:
  4141                              <1> ;	push	edx
  4142                              <1> ;	; eax = page directory
  4143                              <1> ;	; ebx = virtual address
  4144                              <1> ;	call	get_pte
  4145                              <1> ;	mov	ebx, edx	; PTE address
  4146                              <1> ;	pop	edx
  4147                              <1> ;	; 10/06/2016
  4148                              <1> ;	jc	short swpqs_13 ; empty PDE
  4149                              <1> ;	; EAX = PTE value
  4150                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4151                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4152                              <1> ;			        ; from the queue (head)
  4153                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4154                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4155                              <1> ;			        ; from the queue (head) 	
  4156                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4157                              <1> ;	;jnz	short swpqs_11  ; present
  4158                              <1> ;			        ; accessed page
  4159                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4160                              <1> ;	jc	short swpqs_11  ; accessed page
  4161                              <1> ;
  4162                              <1> ;	dec	ecx
  4163                              <1> ;	mov	[swpq_count], cx
  4164                              <1> ;       jz      short swpqs_10
  4165                              <1> ;		; esi = head + 4
  4166                              <1> ;		; edi = head
  4167                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4168                              <1> ;swpqs_10:
  4169                              <1> ;	mov	[edi], ecx ; 0
  4170                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4171                              <1> ;
  4172                              <1> ;swpqs_11:
  4173                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4174                              <1> ;	; Rotation (head -> tail)
  4175                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4176                              <1> ;	jz	short swpqs_10
  4177                              <1> ;		; esi = head + 4
  4178                              <1> ;		; edi = head
  4179                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4180                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4181                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4182                              <1> ;
  4183                              <1> ;	mov	cx, [swpq_count]
  4184                              <1> ;
  4185                              <1> ;swpqs_12:
  4186                              <1> ;	mov	esi, swap_queue ; head
  4187                              <1> ;       jmp     swpqs_7
  4188                              <1> ;
  4189                              <1> ;swpqs_13:
  4190                              <1> ;	dec	ecx
  4191                              <1> ;	mov	[swpq_count], cx
  4192                              <1> ;       jz      swpqs_5
  4193                              <1> ;	jmp	short swpqs_12
  4194                              <1> 
  4195                              <1> ; 24/12/2021
  4196                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4197                              <1> 
  4198                              <1> ;add_to_swap_queue:
  4199                              <1> 	; 20/02/2017
  4200                              <1> 	; 20/07/2015
  4201                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4202                              <1> 	;
  4203                              <1> 	; Adds new page to swap queue
  4204                              <1> 	; (page directories and page tables must not be added
  4205                              <1> 	; to swap queue)	
  4206                              <1> 	;
  4207                              <1> 	; INPUT ->
  4208                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4209                              <1> 	;	[u.uno]
  4210                              <1> 	;	20/02/2017
  4211                              <1> 	;	(Linear address = CORE + user's virtual address)
  4212                              <1> 	;
  4213                              <1> 	; OUTPUT ->
  4214                              <1> 	;	EAX = [swpq_count]
  4215                              <1> 	;	      (after the PTE has been added)
  4216                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4217                              <1> 	;	      the PTE could not be added.
  4218                              <1> 	;
  4219                              <1> 	; Modified Registers -> EAX
  4220                              <1> 	;
  4221                              <1> ;	push	ebx
  4222                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4223                              <1> ;	mov	bl, [u.uno] ; current process number
  4224                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4225                              <1> ;				 ; it is already on the queue
  4226                              <1> ;		; then add it to the tail of the queue
  4227                              <1> ;	movzx	eax, word [swpq_count]
  4228                              <1> ;	cmp	ax, 1024
  4229                              <1> ;	jb	short atsq_1
  4230                              <1> ;	sub	ax, ax
  4231                              <1> ;	pop	ebx
  4232                              <1> ;	retn
  4233                              <1> ;atsq_1:
  4234                              <1> ;	push	esi
  4235                              <1> ;	mov	esi, swap_queue
  4236                              <1> ;	and	ax, ax
  4237                              <1> ;	jz	short atsq_2
  4238                              <1> ;	shl	ax, 2	; convert to offset
  4239                              <1> ;	add	esi, eax
  4240                              <1> ;	shr	ax, 2
  4241                              <1> ;atsq_2:
  4242                              <1> ;	inc	ax
  4243                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4244                              <1> ;	mov	[swpq_count], ax
  4245                              <1> ;	pop	esi
  4246                              <1> ;	pop	ebx
  4247                              <1> ;	retn
  4248                              <1> 
  4249                              <1> ; 24/12/2021
  4250                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4251                              <1> 
  4252                              <1> ;unlink_swap_block:
  4253                              <1> 	; 15/09/2015
  4254                              <1> 	; 30/04/2015
  4255                              <1> 	; 18/04/2015
  4256                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4257                              <1> 	;
  4258                              <1> 	; INPUT -> 
  4259                              <1> 	;	EAX = swap disk/file offset address
  4260                              <1> 	;	      (bit 1 to bit 31)
  4261                              <1> 	; OUTPUT ->
  4262                              <1> 	;	[swpd_free] is increased
  4263                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4264                              <1> 	;
  4265                              <1> 	; Modified Registers -> EAX
  4266                              <1> 	;
  4267                              <1> ;	push	ebx
  4268                              <1> ;	push	edx
  4269                              <1> ;	;
  4270                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4271                              <1> ;				     ; 3 bits right
  4272                              <1> ;				     ; to get swap block/page number
  4273                              <1> ;	mov	edx, eax
  4274                              <1> ;	; 15/09/2015
  4275                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4276                              <1> ;				     ; (1 allocation bit = 1 page)
  4277                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4278                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4279                              <1> ;				     ; (to get 32 bit position)			
  4280                              <1> ;	;
  4281                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4282                              <1> ;	add	ebx, edx
  4283                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4284                              <1> ;				     ; (allocation bit position)	 
  4285                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4286                              <1> ;				     ; than the address in 'swpd_next' ?
  4287                              <1> ;				     ; (next/first free block value)		
  4288                              <1> ;	jnb	short uswpbl_1	     ; no	
  4289                              <1> ;	mov	[swpd_next], eax     ; yes	
  4290                              <1> ;uswpbl_1:
  4291                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4292                              <1> ;				     ; set relevant bit to 1.
  4293                              <1> ;				     ; set CF to the previous bit value	
  4294                              <1> ;	cmc			     ; complement carry flag	
  4295                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4296                              <1> ;				     ; if the block is already deallocated
  4297                              <1> ;				     ; before.	
  4298                              <1> ;       inc     dword [swpd_free]
  4299                              <1> ;uswpbl_2:
  4300                              <1> ;	pop	edx
  4301                              <1> ;	pop	ebx
  4302                              <1> ;	retn
  4303                              <1> 
  4304                              <1> ; 24/12/2021
  4305                              <1> ; ('link_swap_block' procedure call is disabled)
  4306                              <1> 
  4307                              <1> ;link_swap_block:
  4308                              <1> 	; 01/07/2015
  4309                              <1> 	; 18/04/2015
  4310                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4311                              <1> 	;
  4312                              <1> 	; INPUT -> none
  4313                              <1> 	;
  4314                              <1> 	; OUTPUT ->
  4315                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4316                              <1> 	;	      in sectors (corresponding 
  4317                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4318                              <1> 	;
  4319                              <1> 	;	CF = 1 and EAX = 0 
  4320                              <1> 	; 		   if there is not a free block to be allocated	
  4321                              <1> 	;
  4322                              <1> 	; Modified Registers -> none (except EAX)
  4323                              <1> 	;
  4324                              <1> 
  4325                              <1> ;	;mov	eax, [swpd_free]
  4326                              <1> ;	;and	eax, eax
  4327                              <1> ;	;jz	short out_of_swpspc
  4328                              <1> ;	;
  4329                              <1> ;	push	ebx
  4330                              <1> ;	push	ecx
  4331                              <1> ;	;
  4332                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4333                              <1> ;	mov	ecx, ebx
  4334                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4335                              <1> ;				 ; next_free_swap_block >> 5
  4336                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4337                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4338                              <1> ;lswbl_scan:
  4339                              <1> ;	cmp	ebx, ecx
  4340                              <1> ;	ja	short lswbl_notfound
  4341                              <1> ;	;
  4342                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4343                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4344                              <1> ;			   ; loads the destination with an index to
  4345                              <1> ;			   ; first set bit. (0 -> 31) 
  4346                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4347                              <1> ;	; 01/07/2015
  4348                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4349                              <1> ;			 ;
  4350                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4351                              <1> ;			 ;	  with value of 1 means 
  4352                              <1> ;			 ;	  the corresponding page is free 
  4353                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4354                              <1> ;	add	ebx, 4
  4355                              <1> ;			 ; We return back for searching next page block
  4356                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4357                              <1> ;			 ;	 we always will find at least 1 free block here.
  4358                              <1> ;	jmp    	short lswbl_scan
  4359                              <1> ;	;
  4360                              <1> ;lswbl_notfound:	
  4361                              <1> ;	sub	ecx, swap_alloc_table
  4362                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4363                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4364                              <1> ;	xor	eax, eax
  4365                              <1> ;	mov	[swpd_free], eax
  4366                              <1> ;	stc
  4367                              <1> ;lswbl_ok:
  4368                              <1> ;	pop	ecx
  4369                              <1> ;	pop	ebx
  4370                              <1> ;	retn
  4371                              <1> ;	;
  4372                              <1> ;;out_of_swpspc:
  4373                              <1> ;;	stc
  4374                              <1> ;;	retn
  4375                              <1> ;
  4376                              <1> ;lswbl_found:
  4377                              <1> ;	mov	ecx, ebx
  4378                              <1> ;	sub	ecx, swap_alloc_table
  4379                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4380                              <1> ;				 ; address/offset (to the next)
  4381                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4382                              <1> ;	;
  4383                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4384                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4385                              <1> ;				 ; in the destination.
  4386                              <1> ;				 ;
  4387                              <1> ;				 ; Reset the bit which is corresponding to the 
  4388                              <1> ;				 ; (just) allocated block.
  4389                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4390                              <1> ;	add	eax, ecx	 ; = block number
  4391                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4392                              <1> ;				 ; 1 block =  8 sectors
  4393                              <1> ;	;
  4394                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4395                              <1> ;	;
  4396                              <1> ;	; NOTE: The relevant page table entry will be updated
  4397                              <1> ;	;       according to this EAX value...
  4398                              <1> ;	;
  4399                              <1> ;	jmp	short lswbl_ok
  4400                              <1> 
  4401                              <1> ; 24/12/2021
  4402                              <1> ; ('logical_disk_read' procedure call is disabled)
  4403                              <1> 
  4404                              <1> ;logical_disk_read:
  4405                              <1> 	; 20/07/2015
  4406                              <1> 	; 09/03/2015 (temporary code here)
  4407                              <1> 	;
  4408                              <1> 	; INPUT ->
  4409                              <1> 	; 	ESI = Logical disk description table address
  4410                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4411                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4412                              <1> 	; 	ECX = Sector count
  4413                              <1> 	;
  4414                              <1> 	;
  4415                              <1> ;	retn
  4416                              <1> 
  4417                              <1> ; 24/12/2021
  4418                              <1> ; ('logical_disk_write' procedure call is disabled)
  4419                              <1> 
  4420                              <1> ;logical_disk_write:
  4421                              <1> 	; 20/07/2015
  4422                              <1> 	; 09/03/2015 (temporary code here)
  4423                              <1> 	;
  4424                              <1> 	; INPUT ->
  4425                              <1> 	; 	ESI = Logical disk description table address
  4426                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4427                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4428                              <1> 	; 	ECX = Sector count
  4429                              <1> 	;
  4430                              <1> ;	retn
  4431                              <1> 
  4432                              <1> get_physical_addr:
  4433                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4434                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4435                              <1> 	; 18/10/2015
  4436                              <1> 	; 29/07/2015
  4437                              <1> 	; 20/07/2015
  4438                              <1> 	; 04/06/2015
  4439                              <1> 	; 20/05/2015
  4440                              <1> 	; 28/04/2015
  4441                              <1> 	; 18/04/2015
  4442                              <1> 	; Get physical address
  4443                              <1> 	;     (allocates a new page for user if it is not present)
  4444                              <1> 	;	
  4445                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4446                              <1> 	; (buffer) address to physical address (of the buffer).)
  4447                              <1> 	; ('sys write', 'sys read' system calls...)
  4448                              <1> 	;
  4449                              <1> 	; INPUT ->
  4450                              <1> 	;	EBX = virtual address
  4451                              <1> 	;	u.pgdir = page directory (physical) address
  4452                              <1> 	;
  4453                              <1> 	; OUTPUT ->
  4454                              <1> 	;	EAX = physical address 
  4455                              <1> 	;	EBX = linear address	
  4456                              <1> 	;	EDX = physical address of the page frame
  4457                              <1> 	;	      (with attribute bits)
  4458                              <1> 	;	ECX = byte count within the page frame
  4459                              <1> 	;
  4460                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4461                              <1> 	;
  4462                              <1> 
  4463                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4464 00003326 A1[61700000]        <1> 	mov	eax, [u.pgdir]
  4465                              <1> 
  4466                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4467                              <1> 	
  4468 0000332B 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4469                              <1> 	;
  4470                              <1> 	;mov	eax, [u.pgdir]
  4471 00003331 E816FDFFFF          <1> 	call	get_pte
  4472                              <1> 		; EDX = Page table entry address (if CF=0)
  4473                              <1> 	        ;       Page directory entry address (if CF=1)
  4474                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4475                              <1> 		; EAX = Page table entry value (page address)
  4476                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4477 00003336 731C                <1> 	jnc	short gpa_1
  4478                              <1> 	;
  4479 00003338 E8FDFBFFFF          <1> 	call	allocate_page
  4480 0000333D 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4481                              <1> gpa_0:
  4482 0000333F E867FCFFFF          <1> 	call 	clear_page
  4483                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4484 00003344 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4485                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4486                              <1> 			   ; (user, writable, present page)	
  4487 00003346 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4488 00003348 A1[61700000]        <1> 	mov	eax, [u.pgdir]	
  4489 0000334D E8FAFCFFFF          <1> 	call	get_pte
  4490 00003352 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4491                              <1> gpa_1:
  4492                              <1> 	; EAX = PTE value, EDX = PTE address
  4493 00003354 A801                <1> 	test 	al, PTE_A_PRESENT
  4494 00003356 750A                <1> 	jnz	short gpa_3
  4495 00003358 09C0                <1> 	or	eax, eax
  4496 0000335A 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4497                              <1> 
  4498                              <1> ; 24/12/2021
  4499                              <1> ; ('reload_page' procedure call is disabled)
  4500 0000335C EB2C                <1> 	jmp	short gpa_im_err
  4501                              <1> 
  4502                              <1> 	; 20/07/2015
  4503                              <1> ;	push	ebp
  4504                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4505                              <1> ;	; reload swapped page
  4506                              <1> ;	call	reload_page ; 28/04/2015
  4507                              <1> ;	pop	ebp
  4508                              <1> ;	jc	short gpa_retn
  4509                              <1> gpa_2:
  4510                              <1> ; 24/12/2021
  4511                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4512                              <1> 
  4513                              <1> 	; 20/07/2015
  4514                              <1> 	; 20/05/2015
  4515                              <1> 	; add this page to swap queue
  4516                              <1> ;	push	eax 
  4517                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4518                              <1> ;	call 	add_to_swap_queue
  4519                              <1> ;	pop	eax
  4520                              <1> 		; PTE address in EDX
  4521                              <1> 		; virtual address in EBX
  4522                              <1> 	; EAX = memory page address
  4523 0000335E 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4524                              <1> 				  ; present flag, bit 0 = 1
  4525                              <1> 				  ; user flag, bit 2 = 1	
  4526                              <1> 				  ; writable flag, bit 1 = 1
  4527 00003360 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4528                              <1> gpa_3:
  4529                              <1> 	; 18/10/2015
  4530 00003362 89D9                <1> 	mov	ecx, ebx
  4531 00003364 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4532 0000336A 89C2                <1> 	mov 	edx, eax
  4533 0000336C 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4534 00003370 01C8                <1> 	add	eax, ecx
  4535 00003372 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4536 00003374 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4537 0000337A F8                  <1> 	clc
  4538                              <1> gpa_retn:
  4539 0000337B C3                  <1> 	retn	
  4540                              <1> gpa_4:	
  4541 0000337C E8B9FBFFFF          <1> 	call	allocate_page
  4542 00003381 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4543 00003383 E823FCFFFF          <1> 	call	clear_page
  4544 00003388 EBD4                <1> 	jmp	short gpa_2
  4545                              <1> 
  4546                              <1> gpa_im_err:	
  4547 0000338A B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4548                              <1> 				  ; Major error = 0 (No protection fault)	
  4549 0000338F C3                  <1> 	retn
  4550                              <1> 
  4551                              <1> ; 24/12/2021
  4552                              <1> ; ('reload_page' procedure call is disabled)
  4553                              <1> 
  4554                              <1> ;reload_page:
  4555                              <1> 	; 20/07/2015
  4556                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4557                              <1> 	;
  4558                              <1> 	; Reload (Restore) swapped page at memory
  4559                              <1> 	;
  4560                              <1> 	; INPUT -> 
  4561                              <1> 	;	EBP = Virtual (linear) memory address
  4562                              <1> 	;	EAX = PTE value (swap disk sector address)
  4563                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4564                              <1> 	; OUTPUT ->
  4565                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4566                              <1> 	;
  4567                              <1> 	;	CF = 1 and EAX = error code
  4568                              <1> 	;
  4569                              <1> 	; Modified Registers -> none (except EAX)
  4570                              <1> 	;
  4571                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4572                              <1> ;	push	ebx      ;
  4573                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4574                              <1> ;	call	allocate_page
  4575                              <1> ;	jc	short rlp_im_err
  4576                              <1> ;	xchg 	eax, ebx	
  4577                              <1> ;	; EBX = Physical memory (page) address
  4578                              <1> ;	; EAX = Swap disk (offset) address
  4579                              <1> ;	; EBP = Virtual (linear) memory address
  4580                              <1> ;	call	swap_in
  4581                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4582                              <1> ;	mov	eax, ebx	
  4583                              <1> ;rlp_retn:
  4584                              <1> ;	pop	ebx
  4585                              <1> ;	retn
  4586                              <1> ;	
  4587                              <1> ;rlp_im_err:	
  4588                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4589                              <1> ;				  ; Major error = 0 (No protection fault)	
  4590                              <1> ;	jmp	short rlp_retn
  4591                              <1> ;
  4592                              <1> ;rlp_swp_err:
  4593                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4594                              <1> ;	jmp	short rlp_retn
  4595                              <1> 
  4596                              <1> copy_page_dir:
  4597                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4598                              <1> 	; 19/09/2015
  4599                              <1> 	; temporary - 07/09/2015
  4600                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4601                              <1> 	;
  4602                              <1> 	; INPUT -> 
  4603                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4604                              <1> 	;		    page directory.
  4605                              <1> 	; OUTPUT ->
  4606                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4607                              <1> 	;	       page directory.
  4608                              <1> 	;	(New page directory with new page table entries.)
  4609                              <1> 	;	(New page tables with read only copies of the parent's
  4610                              <1> 	;	pages.)
  4611                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4612                              <1> 	;
  4613                              <1> 	; Modified Registers -> none (except EAX)
  4614                              <1> 	;
  4615 00003390 E8A5FBFFFF          <1> 	call	allocate_page
  4616 00003395 723E                <1> 	jc	short cpd_err
  4617                              <1> 	;
  4618 00003397 55                  <1> 	push	ebp ; 20/07/2015
  4619 00003398 56                  <1> 	push	esi
  4620 00003399 57                  <1> 	push	edi
  4621 0000339A 53                  <1> 	push	ebx
  4622 0000339B 51                  <1> 	push	ecx
  4623 0000339C 8B35[61700000]      <1> 	mov	esi, [u.pgdir]
  4624 000033A2 89C7                <1> 	mov	edi, eax
  4625 000033A4 50                  <1> 	push	eax ; save child's page directory address
  4626                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4627                              <1> 	; (use same system space for all user page tables) 
  4628 000033A5 A5                  <1> 	movsd
  4629 000033A6 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4630 000033AB B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4631                              <1> cpd_0:	
  4632 000033B0 AD                  <1> 	lodsd
  4633                              <1> 	;or	eax, eax
  4634                              <1>         ;jnz	short cpd_1
  4635 000033B1 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4636 000033B3 7508                <1> 	jnz	short cpd_1
  4637                              <1>  	; (virtual address at the end of the page table)	
  4638 000033B5 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4639 000033BB EB0F                <1> 	jmp	short cpd_2
  4640                              <1> cpd_1:	
  4641 000033BD 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4642 000033C1 89C3                <1> 	mov	ebx, eax
  4643                              <1> 	; EBX = Parent's page table address
  4644 000033C3 E81F000000          <1> 	call	copy_page_table
  4645 000033C8 720C                <1> 	jc	short cpd_p_err
  4646                              <1> 	; EAX = Child's page table address
  4647 000033CA 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4648                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4649                              <1> 			 ; (present, writable, user)
  4650                              <1> cpd_2:
  4651 000033CC AB                  <1> 	stosd
  4652 000033CD E2E1                <1> 	loop	cpd_0
  4653                              <1> 	;
  4654 000033CF 58                  <1> 	pop	eax  ; restore child's page directory address
  4655                              <1> cpd_3:
  4656 000033D0 59                  <1> 	pop	ecx
  4657 000033D1 5B                  <1> 	pop	ebx
  4658 000033D2 5F                  <1> 	pop	edi
  4659 000033D3 5E                  <1> 	pop	esi
  4660 000033D4 5D                  <1> 	pop	ebp
  4661                              <1> cpd_err:
  4662 000033D5 C3                  <1> 	retn
  4663                              <1> cpd_p_err:
  4664                              <1> 	; release the allocated pages missing (recover free space)
  4665 000033D6 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4666 000033D7 8B1D[61700000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4667 000033DD E888FCFFFF          <1> 	call 	deallocate_page_dir
  4668 000033E2 29C0                <1> 	sub	eax, eax ; 0
  4669 000033E4 F9                  <1> 	stc
  4670 000033E5 EBE9                <1> 	jmp	short cpd_3	
  4671                              <1> 
  4672                              <1> copy_page_table:
  4673                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4674                              <1> 	; 19/09/2015
  4675                              <1> 	; temporary - 07/09/2015
  4676                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4677                              <1> 	;
  4678                              <1> 	; INPUT -> 
  4679                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4680                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4681                              <1> 	; OUTPUT ->
  4682                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4683                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4684                              <1> 	;	CF = 1 -> error 
  4685                              <1> 	;
  4686                              <1> 	; Modified Registers -> EBP (except EAX)
  4687                              <1> 	;
  4688 000033E7 E84EFBFFFF          <1> 	call	allocate_page
  4689 000033EC 7244                <1> 	jc	short cpt_err
  4690                              <1> 	;
  4691 000033EE 50                  <1> 	push	eax ; *
  4692                              <1> 	;push 	ebx
  4693 000033EF 56                  <1> 	push	esi
  4694 000033F0 57                  <1> 	push	edi
  4695 000033F1 52                  <1> 	push	edx
  4696 000033F2 51                  <1> 	push	ecx
  4697                              <1> 	;
  4698 000033F3 89DE                <1> 	mov	esi, ebx
  4699 000033F5 89C7                <1> 	mov	edi, eax
  4700 000033F7 89C2                <1> 	mov	edx, eax
  4701 000033F9 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4702                              <1> cpt_0:
  4703 000033FF AD                  <1> 	lodsd
  4704 00003400 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4705                              <1> 	;jnz	short cpt_1 (*)
  4706                              <1> 	; 24/12/2021
  4707                              <1> 	;and	eax, eax (*)
  4708 00003402 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4709                              <1> 	
  4710                              <1> ; 24/12/2021
  4711                              <1> ; ('reload_page' procedure call is disabled)
  4712                              <1> ;
  4713                              <1> ;	; ebp = virtual (linear) address of the memory page
  4714                              <1> ;	call	reload_page ; 28/04/2015
  4715                              <1> ;	jc	short cpt_p_err
  4716                              <1> cpt_1:
  4717 00003404 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4718 00003408 89C1                <1> 	mov	ecx, eax
  4719                              <1> 	; Allocate a new page for the child process
  4720 0000340A E82BFBFFFF          <1> 	call	allocate_page
  4721 0000340F 721C                <1> 	jc	short cpt_p_err
  4722 00003411 57                  <1> 	push	edi
  4723 00003412 56                  <1> 	push	esi
  4724 00003413 89CE                <1> 	mov	esi, ecx
  4725 00003415 89C7                <1> 	mov	edi, eax
  4726 00003417 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4727 0000341C F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4728 0000341E 5E                  <1> 	pop	esi
  4729 0000341F 5F                  <1> 	pop	edi
  4730                              <1> 	; 
  4731                              <1> ; 24/12/2021
  4732                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4733                              <1> ;
  4734                              <1> ;	push	ebx
  4735                              <1> ;	push	eax
  4736                              <1> ;	mov	ebx, ebp
  4737                              <1> ;	; ebx = virtual address of the memory page
  4738                              <1> ;	call	add_to_swap_queue
  4739                              <1> ;	pop	eax
  4740                              <1> ;	pop	ebx
  4741                              <1> 	;
  4742                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4743 00003420 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4744                              <1> cpt_2:
  4745 00003422 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4746                              <1> 	;
  4747 00003423 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4748                              <1> 	;
  4749 00003429 39D7                <1> 	cmp	edi, edx
  4750 0000342B 72D2                <1> 	jb	short cpt_0
  4751                              <1> cpt_p_err:
  4752 0000342D 59                  <1> 	pop	ecx
  4753 0000342E 5A                  <1> 	pop	edx
  4754 0000342F 5F                  <1> 	pop	edi
  4755 00003430 5E                  <1> 	pop	esi
  4756                              <1> 	;pop	ebx
  4757 00003431 58                  <1> 	pop	eax ; *
  4758                              <1> cpt_err:
  4759 00003432 C3                  <1> 	retn
  4760                              <1> 
  4761                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4762                              <1> 
  4763                              <1> ;; Data:
  4764                              <1> 
  4765                              <1> ; 09/03/2015
  4766                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4767                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4768                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4769                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4770                              <1> ;swpd_next:  dd 0 ; next free page block
  4771                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  1991                                  %include 'sysdefs.inc' ; 09/03/2015
  1992                              <1> ; Retro UNIX 386 v1.1 Kernel - SYSDEFS.INC
  1993                              <1> ; Last Modification: 24/12/2021
  1994                              <1> ;
  1995                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  1996                              <1> ; (Modified from 
  1997                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  1998                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  1999                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2000                              <1> ; ----------------------------------------------------------------------------
  2001                              <1> ;
  2002                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2003                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2004                              <1> ; <Bell Laboratories (17/3/1972)>
  2005                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2006                              <1> ;
  2007                              <1> ; ****************************************************************************
  2008                              <1> 
  2009                              <1> nproc 	equ	16  ; number of processes
  2010                              <1> nfiles 	equ	50
  2011                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2012                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2013                              <1> 
  2014                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2015                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2016                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2017                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2018                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2019                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2020                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2021                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2022                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2023                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2024                              <1> 	; '/core' dump file size = 32768 bytes
  2025                              <1>  
  2026                              <1> ; 08/03/2014 
  2027                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2028                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2029                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2030                              <1> 
  2031                              <1> ; 30/08/2013
  2032                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2033                              <1> 
  2034                              <1> ; 05/02/2014
  2035                              <1> ; process status
  2036                              <1> ;SFREE 	equ 0
  2037                              <1> ;SRUN	equ 1
  2038                              <1> ;SWAIT	equ 2
  2039                              <1> ;SZOMB	equ 3
  2040                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2041                              <1> 
  2042                              <1> ; 09/03/2015
  2043                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2044                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2045                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2046                              <1> 
  2047                              <1> ; 17/09/2015
  2048                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2049                              <1> 
  2050                              <1> ; 21/09/2015 (36) 
  2051                              <1> ; 01/07/2015 (35)
  2052                              <1> ; 14/07/2013 (0-34)
  2053                              <1> ; UNIX v1 system calls
  2054                              <1> _rele 	equ 0
  2055                              <1> _exit 	equ 1
  2056                              <1> _fork 	equ 2
  2057                              <1> _read 	equ 3
  2058                              <1> _write	equ 4
  2059                              <1> _open	equ 5
  2060                              <1> _close 	equ 6
  2061                              <1> _wait 	equ 7
  2062                              <1> _creat 	equ 8
  2063                              <1> _link 	equ 9
  2064                              <1> _unlink	equ 10
  2065                              <1> _exec	equ 11
  2066                              <1> _chdir	equ 12
  2067                              <1> _time 	equ 13
  2068                              <1> _mkdir 	equ 14
  2069                              <1> _chmod	equ 15
  2070                              <1> _chown	equ 16
  2071                              <1> _break	equ 17
  2072                              <1> _stat	equ 18
  2073                              <1> _seek	equ 19
  2074                              <1> _tell 	equ 20
  2075                              <1> _mount	equ 21
  2076                              <1> _umount	equ 22
  2077                              <1> _setuid	equ 23
  2078                              <1> _getuid	equ 24
  2079                              <1> _stime	equ 25
  2080                              <1> _quit	equ 26	
  2081                              <1> _intr	equ 27
  2082                              <1> _fstat	equ 28
  2083                              <1> _emt 	equ 29
  2084                              <1> _mdate 	equ 30
  2085                              <1> _stty 	equ 31
  2086                              <1> _gtty	equ 32
  2087                              <1> _ilgins	equ 33
  2088                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2089                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2090                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2091                              <1> 
  2092                              <1> %macro sys 1-4
  2093                              <1>     ; 13/04/2015
  2094                              <1>     ; Retro UNIX 386 v1 system call.		
  2095                              <1>     mov eax, %1
  2096                              <1>     %if %0 >= 2   
  2097                              <1>         mov ebx, %2
  2098                              <1>         %if %0 >= 3    
  2099                              <1>             mov ecx, %3
  2100                              <1>             %if %0 = 4
  2101                              <1>                mov edx, %4   
  2102                              <1>             %endif
  2103                              <1>         %endif
  2104                              <1>     %endif
  2105                              <1>     int 30h	   
  2106                              <1> %endmacro
  2107                              <1> 
  2108                              <1> ; 13/05/2015 - ERROR CODES
  2109                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2110                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2111                              <1> ; 14/05/2015
  2112                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2113                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2114                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2115                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2116                              <1> ; 16/05/2015		
  2117                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2118                              <1> ; 18/05/2015
  2119                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2120                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2121                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2122                              <1> ; 07/06/2015
  2123                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2124                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2125                              <1> ; 09/06/2015
  2126                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2127                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2128                              <1> ; 16/06/2015
  2129                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2130                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2131                              <1> ; 22/06/2015
  2132                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2133                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2134                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2135                              <1> ; 23/06/2015
  2136                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2137                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2138                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2139                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2140                              <1> ; 27/06/2015
  2141                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2142                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2143                              <1> ; 29/06/2015
  2144                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2145                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error	
  2146                              <1> 
  2147                              <1> ; 26/08/2015
  2148                              <1> ; 24/07/2015
  2149                              <1> ; 24/06/2015
  2150                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2151                              <1> ; 01/07/2015
  2152                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2153                              <1> ; 24/12/2021
  2154                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  1992                                  %include 'u0.s'        ; 15/03/2015
  1993                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS0.INC
  1994                              <1> ; Last Modification: 24/12/2021
  1995                              <1> ; ----------------------------------------------------------------------------
  1996                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1997                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1998                              <1> ;
  1999                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2000                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2001                              <1> ; <Bell Laboratories (17/3/1972)>
  2002                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2003                              <1> ;
  2004                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2005                              <1> ;
  2006                              <1> ; ****************************************************************************
  2007                              <1> 
  2008                              <1> sys_init:
  2009                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2010                              <1> 	; 18/10/2015
  2011                              <1> 	; 28/08/2015
  2012                              <1> 	; 24/08/2015
  2013                              <1> 	; 14/08/2015
  2014                              <1> 	; 24/07/2015 
  2015                              <1> 	; 02/07/2015
  2016                              <1> 	; 01/07/2015
  2017                              <1> 	; 23/06/2015
  2018                              <1> 	; 15/04/2015
  2019                              <1> 	; 13/04/2015
  2020                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2021                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2022                              <1> 	;
  2023                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2024                              <1> 	;
  2025                              <1> 	; 14/02/2014
  2026                              <1> 	; 14/07/2013
  2027                              <1> 	;;mov	ax, 41
  2028                              <1> 	; 24/12/2021
  2029                              <1> 	;xor	eax, eax
  2030                              <1> 	;mov	al, 41
  2031                              <1> 	;mov	[rootdir], ax
  2032                              <1> 	;mov	[u.cdir], ax
  2033                              <1> 	;;and	al, 1 ; 15/04/2015
  2034                              <1> 	;inc	al  ; ax = 1
  2035 00003433 B001                <1> 	mov	al, 1
  2036 00003435 A2[57700000]        <1> 	mov	[u.uno], al
  2037                              <1> 	;mov	[mpid], ax
  2038                              <1> 	;mov	[p.pid], ax
  2039 0000343A A2[F66F0000]        <1> 	mov	[mpid], al
  2040 0000343F A2[F66C0000]        <1> 	mov	[p.pid], al	
  2041 00003444 A2[866D0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2042                              <1> 	; 24/12/2021
  2043 00003449 B029                <1> 	mov	al, 41
  2044                              <1> 	;mov	[rootdir], ax
  2045                              <1> 	;mov	[u.cdir], ax
  2046 0000344B A2[F86F0000]        <1> 	mov	[rootdir], al
  2047 00003450 A2[0C700000]        <1> 	mov	[u.cdir], al
  2048                              <1> 	;
  2049 00003455 B004                <1> 	mov	al, time_count ; 30/08/2013
  2050 00003457 A2[4A700000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2051                              <1> 	; 02/07/2015
  2052 0000345C A1[286C0000]        <1> 	mov	eax, [k_page_dir]
  2053                              <1> 	;sub	eax, eax
  2054 00003461 A3[61700000]        <1> 	mov	[u.pgdir], eax ; reset
  2055                              <1> 	; 18/10/2015
  2056                              <1> 	;mov	[u.ppgdir], eax ; 0
  2057                              <1>         ;
  2058 00003466 E854030000          <1>  	call	epoch
  2059 0000346B A3[547E0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2060                              <1> 	; 17/07/2013
  2061 00003470 E8AE060000          <1> 	call 	bf_init ; buffer initialization 
  2062                              <1> 	; 23/06/2015
  2063 00003475 E8C0FAFFFF          <1> 	call	allocate_page
  2064                              <1> 	;;jc	error
  2065                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2066                              <1> 	; 24/12/2021
  2067 0000347A 7305                <1> 	jnc	short sysinit_1
  2068 0000347C E99C000000          <1> 	jmp	panic
  2069                              <1> sysinit_1:
  2070 00003481 A3[58700000]        <1> 	mov	[u.upage], eax ; user structure page	
  2071 00003486 A3[966D0000]        <1> 	mov	[p.upage], eax
  2072                              <1> 	;
  2073 0000348B E81BFBFFFF          <1> 	call	clear_page
  2074                              <1> 	;
  2075                              <1> 	; 14/08/2015
  2076 00003490 FA                  <1> 	cli
  2077                              <1> 	; 14/03/2015
  2078                              <1> 	; 17/01/2014
  2079 00003491 E8DA010000          <1> 	call	sp_init ; serial port initialization
  2080                              <1> 	; 14/08/2015
  2081 00003496 FB                  <1> 	sti
  2082                              <1> 	;
  2083                              <1> 	; 30/06/2015
  2084                              <1> 	;mov	esi, kernel_init_ok_msg
  2085                              <1> 	;call 	print_msg
  2086                              <1> 	;
  2087 00003497 30DB                <1> 	xor	bl, bl ; video page 0
  2088                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2089 00003499 E87A2D0000          <1> 	call 	vp_clr  ; 17/07/2013
  2090 0000349E FEC3                <1> 	inc	bl
  2091 000034A0 80FB08              <1> 	cmp	bl, 8
  2092 000034A3 72F4                <1> 	jb	short vp_clr_nxt
  2093                              <1> 	;
  2094                              <1> 	; 24/07/2015
  2095                              <1> 	;push    KDATA
  2096                              <1>         ;push    esp
  2097                              <1> 	;mov	[tss.esp0], esp
  2098                              <1>         ;mov     word [tss.ss0], KDATA
  2099                              <1> 	;
  2100                              <1> 	; 24/08/2015
  2101                              <1> 	;; temporary (01/07/2015)
  2102 000034A5 C605[4A700000]04    <1> 	mov	byte [u.quant], time_count ; 4 
  2103                              <1> 			       ; it is not needed here !
  2104                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2105 000034AC FE0D[FF6F0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2106                              <1> 			      ; 0 = executing a system call
  2107                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2108                              <1> 	;
  2109                              <1> 	;;; 06/08/2015
  2110                              <1> 	;;;call	getch ; wait for a key stroke
  2111                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2112                              <1> ;;sys_init_msg_wait:
  2113                              <1> ;;	push 	ecx
  2114                              <1> ;;	mov	al, 1
  2115                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2116                              <1> ;;	call	getc_n
  2117                              <1> ;;	pop	ecx
  2118                              <1> ;;	jnz	short sys_init_msg_ok
  2119                              <1> ;;	loop	sys_init_msg_wait
  2120                              <1> 	;
  2121                              <1> ;;sys_init_msg_ok:
  2122                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2123 000034B2 6A10                <1> 	push	KDATA ; ss
  2124 000034B4 54                  <1> 	push	esp
  2125 000034B5 9C                  <1> 	pushfd
  2126 000034B6 6A08                <1> 	push	KCODE ; cs
  2127 000034B8 68[EC340000]        <1> 	push	init_exec ; eip
  2128 000034BD 8925[00700000]      <1> 	mov	[u.sp], esp
  2129 000034C3 1E                  <1> 	push	ds
  2130 000034C4 06                  <1> 	push	es
  2131 000034C5 0FA0                <1> 	push	fs
  2132 000034C7 0FA8                <1> 	push	gs	
  2133 000034C9 60                  <1> 	pushad
  2134 000034CA 8925[04700000]      <1> 	mov	[u.usp], esp
  2135 000034D0 E8FD1A0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2136                              <1> 		      ; and interrupt return components (for IRET)
  2137 000034D5 61                  <1> 	popad
  2138 000034D6 6658                <1> 	pop	ax ; gs
  2139 000034D8 6658                <1> 	pop	ax ; fs
  2140 000034DA 6658                <1> 	pop	ax ; es
  2141 000034DC 6658                <1> 	pop	ax ; ds	
  2142 000034DE 58                  <1> 	pop	eax ; eip (init_exec)
  2143 000034DF 6658                <1> 	pop	ax ; cs (KCODE)
  2144 000034E1 58                  <1> 	pop	eax ; E-FLAGS
  2145 000034E2 58                  <1> 	pop	eax ; esp
  2146 000034E3 6658                <1> 	pop	ax ; ss (KDATA)
  2147                              <1> 	;
  2148 000034E5 31C0                <1> 	xor	eax, eax ; 0
  2149 000034E7 A3[65700000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2150                              <1> 	;
  2151                              <1> 	; 02/07/2015
  2152                              <1> 	; [u.pgdir ] = [k_page_dir]
  2153                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2154                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2155                              <1> init_exec:
  2156                              <1> 	; 13/03/2013
  2157                              <1> 	; 24/07/2013
  2158 000034EC BB[13350000]        <1> 	mov	ebx, init_file
  2159 000034F1 B9[0B350000]        <1> 	mov	ecx, init_argp
  2160                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2161                              <1> 	; ECX contains address of argument list pointer
  2162                              <1> 	;
  2163                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2164                              <1> 			      ; 0 = executing a system call
  2165                              <1> 	sys	_exec  ; execute file
  2093                              <2> 
  2094                              <2> 
  2095 000034F6 B80B000000          <2>  mov eax, %1
  2096                              <2>  %if %0 >= 2
  2097                              <2>  mov ebx, %2
  2098                              <2>  %if %0 >= 3
  2099                              <2>  mov ecx, %3
  2100                              <2>  %if %0 = 4
  2101                              <2>  mov edx, %4
  2102                              <2>  %endif
  2103                              <2>  %endif
  2104                              <2>  %endif
  2105 000034FB CD30                <2>  int 30h
  2166 000034FD 731E                <1> 	jnc	short panic
  2167                              <1> 	;
  2168 000034FF BE[38690000]        <1> 	mov	esi, etc_init_err_msg
  2169 00003504 E837000000          <1> 	call 	print_msg
  2170 00003509 EB1C                <1> 	jmp	short key_to_reboot
  2171                              <1> 
  2172                              <1> ;align 4
  2173                              <1> init_argp:
  2174 0000350B [13350000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2175                              <1> init_file:
  2176                              <1> 	; 24/08/2015
  2177 00003513 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2177 0000351C 00                  <1>
  2178                              <1> panic:
  2179                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2180                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2181 0000351D BE[1D690000]        <1> 	mov 	esi, panic_msg
  2182 00003522 E819000000          <1> 	call 	print_msg
  2183                              <1> key_to_reboot:
  2184                              <1> 	; 15/11/2015
  2185 00003527 E8382B0000          <1> 	call 	getch 
  2186                              <1> 		; wait for a character from the current tty
  2187                              <1> 	;
  2188 0000352C B00A                <1> 	mov	al, 0Ah
  2189 0000352E 8A1D[566C0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2190 00003534 B407                <1> 	mov	ah, 07h ; Black background, 
  2191                              <1> 			; light gray forecolor
  2192 00003536 E84DDFFFFF          <1> 	call 	write_tty
  2193 0000353B E9E8DBFFFF          <1> 	jmp	cpu_reset 
  2194                              <1> 
  2195                              <1> print_msg:
  2196                              <1> 	; 01/07/2015
  2197                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2198                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2199                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2200                              <1> 	;
  2201                              <1> 	;
  2202 00003540 AC                  <1> 	lodsb
  2203                              <1> pmsg1:
  2204 00003541 56                  <1> 	push 	esi
  2205 00003542 0FB61D[566C0000]    <1> 	movzx	ebx, byte [ptty]
  2206 00003549 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2207 0000354B E838DFFFFF          <1> 	call 	write_tty
  2208 00003550 5E                  <1> 	pop	esi
  2209 00003551 AC                  <1> 	lodsb
  2210 00003552 20C0                <1> 	and 	al, al
  2211 00003554 75EB                <1> 	jnz 	short pmsg1
  2212 00003556 C3                  <1> 	retn
  2213                              <1> 	
  2214                              <1> ctrlbrk:
  2215                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2216                              <1> 	; 12/11/2015
  2217                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2218                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2219                              <1> 	;
  2220                              <1> 	; INT 1Bh (control+break) handler		
  2221                              <1> 	;
  2222                              <1>       	; Retro Unix 8086 v1 feature only!
  2223                              <1>       	;
  2224 00003557 66833D[4C700000]00  <1> 	cmp 	word [u.intr], 0
  2225 0000355F 7641                <1> 	jna 	short cbrk4
  2226                              <1> cbrk0:
  2227                              <1> 	; 12/11/2015
  2228                              <1> 	; 06/12/2013
  2229 00003561 66833D[4E700000]00  <1> 	cmp 	word [u.quit], 0
  2230 00003569 7437                <1> 	jz	short cbrk4
  2231                              <1> 	;
  2232                              <1> 	; 20/09/2013	
  2233                              <1> 	;push 	ax
  2234                              <1> 	; 24/12/2021
  2235 0000356B 50                  <1> 	push	eax ; *
  2236 0000356C A0[566C0000]        <1> 	mov	al, [ptty]
  2237                              <1> 	;
  2238                              <1> 	; 12/11/2015
  2239                              <1> 	;
  2240                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2241                              <1> 	; or ctrl+break from console (pseudo) tty
  2242                              <1> 	; (!redirection!)
  2243                              <1> 	;
  2244 00003571 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2245 00003573 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2246                              <1> 	;	
  2247                              <1> 	; Serial port interrupt handler sets [ptty]
  2248                              <1> 	; to the port's tty number (as temporary).
  2249                              <1> 	;
  2250                              <1> 	; If active process is using a stdin or 
  2251                              <1> 	; stdout redirection (by the shell),
  2252                              <1>         ; console tty keyboard must be available
  2253                              <1> 	; to terminate running process,
  2254                              <1> 	; in order to prevent a deadlock. 
  2255                              <1> 	;
  2256 00003575 52                  <1> 	push	edx ; **
  2257 00003576 0FB615[57700000]    <1> 	movzx	edx, byte [u.uno]
  2258 0000357D 3A82[556D0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2259 00003583 5A                  <1> 	pop	edx ; **
  2260 00003584 7412                <1> 	je	short cbrk2
  2261                              <1> cbrk1:
  2262 00003586 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2263                              <1> 	; 06/12/2013
  2264 00003588 3A05[38700000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2265 0000358E 7408                <1> 	je	short cbrk2	
  2266 00003590 3A05[39700000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2267 00003596 7509                <1> 	jne	short cbrk3	
  2268                              <1> cbrk2:
  2269                              <1> 	;; 06/12/2013
  2270                              <1> 	;mov	ax, [u.quit]
  2271                              <1> 	;and	ax, ax
  2272                              <1> 	;jz	short cbrk3
  2273                              <1> 	;
  2274                              <1> 	;xor	ax, ax ; 0
  2275                              <1> 	;dec	ax
  2276                              <1> 	; 24/12/2021
  2277 00003598 31C0                <1> 	xor	eax, eax ; 0
  2278 0000359A 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2279                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2280 0000359B 66A3[4E700000]      <1> 	mov	[u.quit], ax
  2281                              <1> cbrk3:
  2282                              <1> 	;pop	ax
  2283                              <1> 	; 24/12/2021
  2284 000035A1 58                  <1> 	pop	eax ; *
  2285                              <1> cbrk4:
  2286 000035A2 C3                  <1> 	retn
  2287                              <1> 
  2288                              <1> com2_int:
  2289                              <1> 	; 07/11/2015 
  2290                              <1> 	; 24/10/2015
  2291                              <1> 	; 23/10/2015
  2292                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2293                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2294                              <1> 	; < serial port 2 interrupt handler >
  2295                              <1> 	;
  2296 000035A3 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2297                              <1> 	;push	eax
  2298 000035A6 66B80900            <1> 	mov	ax, 9
  2299 000035AA EB07                <1> 	jmp	short comm_int
  2300                              <1> com1_int:
  2301                              <1> 	; 07/11/2015
  2302                              <1> 	; 24/10/2015
  2303 000035AC 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2304                              <1> 	; 23/10/2015
  2305                              <1> 	;push	eax
  2306 000035AF 66B80800            <1> 	mov	ax, 8
  2307                              <1> comm_int:
  2308                              <1> 	; 20/11/2015
  2309                              <1> 	; 18/11/2015
  2310                              <1> 	; 17/11/2015
  2311                              <1> 	; 16/11/2015
  2312                              <1> 	; 09/11/2015
  2313                              <1> 	; 08/11/2015
  2314                              <1> 	; 07/11/2015
  2315                              <1> 	; 06/11/2015 (serial4.asm, 'serial')	
  2316                              <1> 	; 01/11/2015
  2317                              <1> 	; 26/10/2015
  2318                              <1> 	; 23/10/2015
  2319 000035B3 53                  <1> 	push	ebx
  2320 000035B4 56                  <1> 	push	esi
  2321 000035B5 57                  <1> 	push	edi
  2322 000035B6 1E                  <1> 	push 	ds
  2323 000035B7 06                  <1> 	push 	es
  2324                              <1> 	; 18/11/2015
  2325 000035B8 0F20DB              <1> 	mov	ebx, cr3
  2326 000035BB 53                  <1> 	push	ebx ; ****
  2327                              <1> 	;
  2328 000035BC 51                  <1> 	push	ecx ; ***
  2329 000035BD 52                  <1> 	push	edx ; **
  2330                              <1> 	;
  2331 000035BE BB10000000          <1> 	mov	ebx, KDATA
  2332 000035C3 8EDB                <1> 	mov	ds, bx
  2333 000035C5 8EC3                <1> 	mov	es, bx
  2334                              <1> 	;
  2335 000035C7 8B0D[286C0000]      <1> 	mov	ecx, [k_page_dir]
  2336 000035CD 0F22D9              <1> 	mov	cr3, ecx
  2337                              <1> 	; 20/11/2015
  2338                              <1> 	; Interrupt identification register
  2339 000035D0 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2340                              <1> 	;
  2341 000035D4 3C08                <1> 	cmp 	al, 8 
  2342 000035D6 7702                <1> 	ja 	short com_i0
  2343                              <1> 	;
  2344                              <1> 	; 20/11/2015
  2345                              <1> 	; 17/11/2015
  2346                              <1> 	; 16/11/2015
  2347                              <1> 	; 15/11/2015
  2348                              <1> 	; 24/10/2015
  2349                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2350                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2351                              <1> 	; < serial port 1 interrupt handler >
  2352                              <1> 	;
  2353 000035D8 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2354                              <1> com_i0:
  2355                              <1> 	;push	eax ; *
  2356                              <1> 	; 07/11/2015
  2357 000035DA A2[966C0000]        <1> 	mov 	byte [ccomport], al
  2358                              <1> 	; 09/11/2015
  2359 000035DF 0FB7D8              <1> 	movzx	ebx, ax ; 8 or 9
  2360                              <1> 	; 17/11/2015
  2361                              <1>  	; reset request for response status
  2362 000035E2 88A3[8C6C0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2363                              <1> 	;
  2364                              <1> 	; 20/11/2015
  2365 000035E8 EC                  <1> 	in	al, dx		; read interrupt id. register
  2366 000035E9 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2367 000035EB 2404                <1> 	and	al, 4		; received data available?	
  2368 000035ED 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2369                              <1> 	;
  2370                              <1> 	; 20/11/2015
  2371 000035EF 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2372 000035F2 EC                  <1> 	in	al, dx     	; read character
  2373                              <1> 	;JMP	$+2	   	; I/O DELAY
  2374                              <1> 	; 08/11/2015
  2375                              <1> 	; 07/11/2015
  2376 000035F3 89DE                <1> 	mov	esi, ebx 
  2377 000035F5 89DF                <1> 	mov	edi, ebx
  2378 000035F7 81C6[906C0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2379 000035FD 81C7[926C0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2380 00003603 8806                <1> 	mov	[esi], al ; received char (current char)
  2381                              <1> 	; query
  2382 00003605 20C0                <1> 	and	al, al
  2383 00003607 7527                <1> 	jnz	short com_i2
  2384                              <1>    	; response
  2385                              <1> 	; 17/11/2015
  2386                              <1> 	; set request for response status
  2387 00003609 FE83[8C6C0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2388                              <1> 	;
  2389 0000360F 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2390 00003613 EC                  <1> 	in	al, dx	   	; read line status register 
  2391 00003614 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2392 00003616 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2393 00003618 7445                <1> 	jz	short com_eoi 	; no
  2394 0000361A B0FF                <1> 	mov 	al, 0FFh   	; response			
  2395 0000361C 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2396 00003620 EE                  <1> 	out	dx, al	   	; send on serial port
  2397                              <1> 	; 17/11/2015
  2398 00003621 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2399 00003624 7502                <1> 	jne 	short com_i1    ; no
  2400 00003626 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2401                              <1> com_i1:
  2402                              <1> 	; 17/11/2015
  2403                              <1> 	; reset request for response status (again)
  2404 00003628 FE8B[8C6C0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2405 0000362E EB2F                <1> 	jmp	short com_eoi
  2406                              <1> com_i2:	
  2407                              <1> 	; 08/11/2015
  2408 00003630 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2409 00003632 7417                <1> 	je	short com_i3	; (check for response signal)
  2410                              <1> 	; 07/11/2015
  2411 00003634 3C04                <1> 	cmp	al, 04h	; EOT
  2412 00003636 751C                <1> 	jne	short com_i4	
  2413                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2414                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2415                              <1> 	; 08/11/2015
  2416                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2417 00003638 861D[566C0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2418 0000363E E814FFFFFF          <1> 	call 	ctrlbrk
  2419 00003643 861D[566C0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2420                              <1> 	;mov	al, 04h ; EOT
  2421                              <1> 	; 08/11/2015
  2422 00003649 EB09                <1> 	jmp	short com_i4	
  2423                              <1> com_i3:
  2424                              <1> 	; 08/11/2015
  2425                              <1> 	; If 0FFh has been received just after a query
  2426                              <1> 	; (schar, ZERO), it is a response signal.
  2427                              <1> 	; 17/11/2015
  2428 0000364B 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2429 0000364E 7704                <1> 	ja	short com_i4 ; no
  2430                              <1> 	; reset query status (schar)
  2431 00003650 8807                <1> 	mov	[edi], al ; 0FFh
  2432 00003652 FEC0                <1> 	inc	al ; 0
  2433                              <1> com_i4:
  2434                              <1> 	; 27/07/2014
  2435                              <1> 	; 09/07/2014
  2436 00003654 D0E3                <1> 	shl	bl, 1	
  2437 00003656 81C3[586C0000]      <1> 	add	ebx, ttychr
  2438                              <1> 	; 23/07/2014 (always overwrite)
  2439                              <1> 	;;cmp	word [ebx], 0
  2440                              <1> 	;;ja	short com_eoi
  2441                              <1> 	;
  2442 0000365C 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2443                              <1> 			    ; scan code = 0
  2444                              <1> com_eoi:
  2445                              <1> 	;mov	al, 20h
  2446                              <1> 	;out	20h, al	   ; end of interrupt
  2447                              <1> 	;
  2448                              <1> 	; 07/11/2015
  2449                              <1>       	;pop	eax ; *
  2450 0000365F A0[966C0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2451                              <1> 	 ; al = tty number (8 or 9)
  2452 00003664 E8431A0000          <1>         call	wakeup
  2453                              <1> com_iret:
  2454                              <1> 	; 23/10/2015
  2455 00003669 5A                  <1> 	pop	edx ; **
  2456 0000366A 59                  <1> 	pop	ecx ; ***
  2457                              <1> 	; 18/11/2015
  2458                              <1> 	;pop	eax ; ****
  2459                              <1> 	;mov	cr3, eax
  2460                              <1> 	;jmp	iiret
  2461 0000366B E9F9D3FFFF          <1> 	jmp	iiretp
  2462                              <1> 
  2463                              <1> ;iiretp: ; 01/09/2015
  2464                              <1> ;	; 28/08/2015
  2465                              <1> ;	pop	eax ; (*) page directory
  2466                              <1> ;	mov	cr3, eax
  2467                              <1> ;iiret:
  2468                              <1> ;	; 22/08/2014
  2469                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2470                              <1> ;	out	20h, al	; 8259 PORT
  2471                              <1> ;	;
  2472                              <1> ;	pop	es
  2473                              <1> ;	pop	ds
  2474                              <1> ;	pop	edi
  2475                              <1> ;	pop	esi
  2476                              <1> ;	pop	ebx ; 29/08/2014
  2477                              <1> ;	pop 	eax
  2478                              <1> ;	iretd
  2479                              <1> 
  2480                              <1> sp_init:
  2481                              <1> 	; 07/11/2015
  2482                              <1> 	; 29/10/2015
  2483                              <1> 	; 26/10/2015
  2484                              <1> 	; 23/10/2015
  2485                              <1> 	; 29/06/2015
  2486                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2487                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2488                              <1> 	; Initialization of Serial Port Communication Parameters
  2489                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2490                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2491                              <1> 	;
  2492                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2493                              <1> 	;
  2494                              <1> 	; INPUT:  (29/06/2015)
  2495                              <1> 	;	AL = 0 for COM1
  2496                              <1> 	;	     1 for COM2
  2497                              <1> 	;	AH = Communication parameters	
  2498                              <1> 	;
  2499                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2500                              <1> 	;	Bit	4	3	2	1	0
  2501                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2502                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2503                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2504                              <1> 	;		11 = even
  2505                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2506                              <1> 	;		Retro UNIX 386 v1 feature only !
  2507                              <1> 	;	Bit	7    6    5  | Baud rate
  2508                              <1> 	;		------------------------
  2509                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2510                              <1> 	;		0    0    1  | 9600 (12)
  2511                              <1> 	;		0    1    0  | 19200 (6) 
  2512                              <1> 	;		0    1	  1  | 38400 (3) 
  2513                              <1> 	;		1    0	  0  | 14400 (8)
  2514                              <1> 	;		1    0	  1  | 28800 (4)
  2515                              <1> 	;		1    1    0  | 57600 (2)
  2516                              <1> 	;		1    1    1  | 115200 (1) 	
  2517                              <1> 	
  2518                              <1> 	; References:	
  2519                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2520                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2521                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2522                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2523                              <1> 	;
  2524                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2525                              <1> 	;
  2526 00003670 BB[926C0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2527 00003675 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2528                              <1> 	 ; 29/10/2015
  2529 00003679 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2530 0000367D E86F000000          <1> 	call	sp_i3	; call A4	
  2531 00003682 A880                <1> 	test	al, 80h
  2532 00003684 7410                <1> 	jz	short sp_i0 ; OK..
  2533                              <1> 		; Error !
  2534                              <1> 	;mov	dx, 3F8h
  2535 00003686 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2536 00003689 66B90E03            <1> 	mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2537 0000368D E85F000000          <1> 	call	sp_i3	; call A4	
  2538 00003692 A880                <1> 	test	al, 80h
  2539 00003694 7508                <1> 	jnz	short sp_i1
  2540                              <1> sp_i0:
  2541                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2542                              <1>         ; (INT 14h initialization code disables interrupts.)
  2543                              <1> 	;
  2544 00003696 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2545 00003699 E8DD000000          <1> 	call	sp_i5 ; 29/06/2015
  2546                              <1> sp_i1:
  2547 0000369E 43                  <1> 	inc	ebx
  2548 0000369F 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2549                              <1> 	 ; 29/10/2015
  2550 000036A3 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2551 000036A7 E845000000          <1> 	call	sp_i3	; call A4	
  2552 000036AC A880                <1> 	test	al, 80h
  2553 000036AE 7410                <1> 	jz	short sp_i2 ; OK..
  2554                              <1> 		; Error !
  2555                              <1> 	;mov	dx, 2F8h
  2556 000036B0 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2557 000036B3 66B90E03            <1> 	mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2558 000036B7 E835000000          <1> 	call	sp_i3	; call A4	
  2559 000036BC A880                <1> 	test	al, 80h
  2560 000036BE 7530                <1> 	jnz	short sp_i7
  2561                              <1> sp_i2:
  2562 000036C0 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2563                              <1> sp_i6:
  2564                              <1> 	;; COM2 - enabling IRQ 3
  2565                              <1> 	; 07/11/2015
  2566                              <1> 	; 26/10/2015
  2567 000036C3 9C                  <1> 	pushf
  2568 000036C4 FA                  <1> 	cli
  2569                              <1> 	;
  2570 000036C5 66BAFC02            <1> 	mov	dx, 2FCh   		; modem control register
  2571 000036C9 EC                  <1> 	in	al, dx 	   		; read register
  2572 000036CA EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2573 000036CC 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2574 000036CE EE                  <1> 	out	dx, al     		; write back to register
  2575 000036CF EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2576 000036D1 66BAF902            <1> 	mov	dx, 2F9h   		; interrupt enable register
  2577 000036D5 EC                  <1> 	in	al, dx     		; read register
  2578 000036D6 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2579                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2580 000036D8 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2581 000036DA EE                  <1> 	out	dx, al 	   		; write back to register
  2582 000036DB EB00                <1> 	JMP	$+2        		; I/O DELAY
  2583 000036DD E421                <1> 	in	al, 21h    		; read interrupt mask register
  2584 000036DF EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2585 000036E1 24F7                <1> 	and	al, 0F7h   		; enable IRQ 3 (COM2)
  2586 000036E3 E621                <1> 	out	21h, al    		; write back to register
  2587                              <1> 	;
  2588                              <1> 	; 23/10/2015
  2589 000036E5 B8[A3350000]        <1> 	mov 	eax, com2_int
  2590 000036EA A3[823B0000]        <1> 	mov	[com2_irq3], eax
  2591                              <1> 	; 26/10/2015
  2592 000036EF 9D                  <1> 	popf	
  2593                              <1> sp_i7:
  2594 000036F0 C3                  <1> 	retn
  2595                              <1> 
  2596                              <1> sp_i3:
  2597                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2598                              <1> 	; 28/10/2015
  2599 000036F1 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2600 000036F3 B000                <1> 	mov	al, 0
  2601 000036F5 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2602 000036F6 EB00                <1> 	JMP	$+2			; I/O DELAY
  2603 000036F8 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2604 000036FB B080                <1> 	mov	al, 80h			
  2605 000036FD EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2606                              <1> 	;-----	SET BAUD RATE DIVISOR
  2607                              <1> 	; 26/10/2015
  2608 000036FE 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2609                              <1> 					; of the divisor value
  2610 00003701 88C8                <1> 	mov	al, cl	; 1
  2611 00003703 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2612                              <1> 					; 2 = 57600 baud
  2613                              <1> 					; 3 = 38400 baud
  2614                              <1> 					; 6 = 19200 baud
  2615                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2616 00003704 EB00                <1> 	JMP	$+2			; I/O DELAY
  2617 00003706 28C0                <1> 	sub	al, al
  2618 00003708 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2619                              <1> 					; of the divisor value
  2620 0000370A EE                  <1> 	out	dx, al ; 0
  2621 0000370B EB00                <1> 	JMP	$+2			; I/O DELAY
  2622                              <1> 	;	
  2623 0000370D 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2624                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2625 0000370F 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2626 00003712 EE                  <1> 	out	dx, al			
  2627 00003713 EB00                <1> 	JMP	$+2			; I/O DELAY
  2628                              <1> 	; 29/10/2015
  2629 00003715 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2630 00003717 30C0                <1> 	xor	al, al			; 0
  2631 00003719 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2632 0000371A EB00                <1> 	JMP	$+2	
  2633                              <1> sp_i4:
  2634                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2635                              <1> 	; 29/06/2015 (line status after modem status)
  2636 0000371C 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2637                              <1> sp_i4s:
  2638 0000371F EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2639 00003720 EB00                <1> 	JMP	$+2			; I/O DELAY
  2640 00003722 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2641 00003724 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2642                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2643 00003726 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2644                              <1> 	; AL = Line status, AH = Modem status
  2645 00003727 C3                  <1> 	retn
  2646                              <1> 
  2647                              <1> sp_status:
  2648                              <1> 	; 29/06/2015
  2649                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2650                              <1> 	; Get serial port status
  2651 00003728 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2652 0000372C 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2653                              <1> 					; dx = 2FEh for COM2
  2654 0000372E EBEF                <1> 	jmp	short sp_i4s
  2655                              <1> 
  2656                              <1> sp_setp: ; Set serial port communication parameters
  2657                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2658                              <1> 	; 07/11/2015
  2659                              <1> 	; 29/10/2015
  2660                              <1> 	; 29/06/2015
  2661                              <1> 	; Retro UNIX 386 v1 feature only !	
  2662                              <1> 	;
  2663                              <1> 	; INPUT:
  2664                              <1> 	;	AL = 0 for COM1
  2665                              <1> 	;	     1 for COM2
  2666                              <1> 	;	AH = Communication parameters (*)
  2667                              <1> 	; OUTPUT:
  2668                              <1> 	;	CL = Line status
  2669                              <1> 	;	CH = Modem status
  2670                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2671                              <1> 	;		 'invalid parameter !' 
  2672                              <1> 	;		 	 or
  2673                              <1> 	;		 'device not ready !' error
  2674                              <1> 	;	
  2675                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2676                              <1> 	;	Bit	4	3	2	1	0
  2677                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2678                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2679                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2680                              <1> 	;		11 = even
  2681                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2682                              <1> 	;		Retro UNIX 386 v1 feature only !
  2683                              <1> 	;	Bit	7    6    5  | Baud rate
  2684                              <1> 	;		------------------------
  2685                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2686                              <1> 	;		0    0    1  | 9600 (12)
  2687                              <1> 	;		0    1    0  | 19200 (6) 
  2688                              <1> 	;		0    1	  1  | 38400 (3) 
  2689                              <1> 	;		1    0	  0  | 14400 (8)
  2690                              <1> 	;		1    0	  1  | 28800 (4)
  2691                              <1> 	;		1    1    0  | 57600 (2)
  2692                              <1> 	;		1    1    1  | 115200 (1) 
  2693                              <1> 	;
  2694                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2695                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2696                              <1> 	;
  2697                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2698                              <1> 	;
  2699 00003730 66BAF803            <1> 	mov	dx, 3F8h
  2700 00003734 BB[926C0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2701 00003739 3C01                <1> 	cmp	al, 1
  2702 0000373B 776C                <1> 	ja 	short sp_invp_err
  2703 0000373D 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2704 0000373F FECE                <1> 	dec	dh ; 2F8h
  2705 00003741 43                  <1> 	inc	ebx ; COM2 control byte offset
  2706                              <1> sp_setp1:
  2707                              <1> 	; 29/10/2015
  2708 00003742 8823                <1> 	mov	[ebx], ah
  2709 00003744 0FB6CC              <1> 	movzx 	ecx, ah
  2710 00003747 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2711 0000374A 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2712 0000374D 8A81[B8370000]      <1> 	mov	al, [ecx+b_div_tbl]
  2713 00003753 6689C1              <1> 	mov	cx, ax
  2714 00003756 E896FFFFFF          <1> 	call	sp_i3
  2715 0000375B 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2716 0000375E A880                <1> 	test	al, 80h
  2717 00003760 740F                <1> 	jz	short sp_setp2
  2718 00003762 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2719                              <1> stp_dnr_err:
  2720 00003765 C705[5D700000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2720 0000376D 0000                <1>
  2721                              <1> 	; CL = Line status, CH = Modem status
  2722 0000376F F9                  <1> 	stc
  2723 00003770 C3                  <1> 	retn
  2724                              <1> sp_setp2:
  2725 00003771 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2726                              <1>         ;jna	sp_i6
  2727                              <1> 		      ; COM1 (3F?h)
  2728                              <1> 	; 24/12/2021
  2729 00003774 7705                <1> 	ja	short sp_i5
  2730 00003776 E948FFFFFF          <1> 	jmp	sp_i6
  2731                              <1> sp_i5: 
  2732                              <1> 	; 07/11/2015
  2733                              <1> 	; 26/10/2015
  2734                              <1> 	; 29/06/2015
  2735                              <1> 	;
  2736                              <1> 	;; COM1 - enabling IRQ 4
  2737 0000377B 9C                  <1> 	pushf
  2738 0000377C FA                  <1> 	cli
  2739 0000377D 66BAFC03            <1> 	mov	dx, 3FCh   		; modem control register
  2740 00003781 EC                  <1> 	in	al, dx 	   		; read register
  2741 00003782 EB00                <1> 	JMP	$+2			; I/O DELAY
  2742 00003784 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2743 00003786 EE                  <1> 	out	dx, al     		; write back to register
  2744 00003787 EB00                <1> 	JMP	$+2			; I/O DELAY
  2745 00003789 66BAF903            <1> 	mov	dx, 3F9h   		; interrupt enable register
  2746 0000378D EC                  <1> 	in	al, dx     		; read register
  2747 0000378E EB00                <1> 	JMP	$+2			; I/O DELAY
  2748                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2749 00003790 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2750 00003792 EE                  <1> 	out	dx, al 	   		; write back to register
  2751 00003793 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2752 00003795 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2753 00003797 EB00                <1> 	JMP	$+2			; I/O DELAY
  2754 00003799 24EF                <1> 	and	al, 0EFh   		; enable IRQ 4 (COM1)
  2755 0000379B E621                <1> 	out	21h, al    		; write back to register
  2756                              <1> 	;
  2757                              <1> 	; 23/10/2015
  2758 0000379D B8[AC350000]        <1> 	mov 	eax, com1_int
  2759 000037A2 A3[7E3B0000]        <1> 	mov	[com1_irq4], eax
  2760                              <1> 	; 26/10/2015
  2761 000037A7 9D                  <1> 	popf
  2762 000037A8 C3                  <1> 	retn
  2763                              <1> 
  2764                              <1> sp_invp_err:
  2765 000037A9 C705[5D700000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2765 000037B1 0000                <1>
  2766 000037B3 31C9                <1> 	xor	ecx, ecx
  2767 000037B5 49                  <1> 	dec	ecx ; 0FFFFh
  2768 000037B6 F9                  <1> 	stc
  2769 000037B7 C3                  <1> 	retn
  2770                              <1> 
  2771                              <1> ; 29/10/2015
  2772                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2773 000037B8 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2774                              <1> 
  2775                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2776                              <1> epoch:
  2777                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2778                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2779                              <1> 	; 'epoch' procedure prototype: 
  2780                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2781                              <1> 	; 14/11/2012
  2782                              <1> 	; unixboot.asm (boot file configuration)
  2783                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2784                              <1> 	; 21/7/2012
  2785                              <1> 	; 15/7/2012
  2786                              <1> 	; 14/7/2012		
  2787                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2788                              <1> 	; compute current date and time as UNIX Epoch/Time
  2789                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2790                              <1> 	;
  2791                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2792                              <1> 	;
  2793 000037BF E81D010000          <1> 	call 	get_rtc_time		; Return Current Time
  2794 000037C4 86E9                <1>         xchg 	ch,cl
  2795 000037C6 66890D[92690000]    <1>         mov 	[hour], cx
  2796 000037CD 86F2                <1>         xchg 	dh,dl
  2797 000037CF 668915[96690000]    <1>         mov 	[second], dx
  2798                              <1> 	;
  2799 000037D6 E837010000          <1>         call 	get_rtc_date		; Return Current Date
  2800 000037DB 86E9                <1>         xchg 	ch,cl
  2801 000037DD 66890D[8C690000]    <1>         mov 	[year], cx
  2802 000037E4 86F2                <1>         xchg 	dh,dl
  2803 000037E6 668915[8E690000]    <1>         mov 	[month], dx
  2804                              <1> 	;
  2805 000037ED 66B93030            <1> 	mov 	cx, 3030h
  2806                              <1> 	;
  2807 000037F1 A0[92690000]        <1> 	mov 	al, [hour] ; Hour
  2808                              <1>         	; AL <= BCD number)
  2809 000037F6 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2810                              <1> 					; AH = AL / 10h
  2811                              <1> 					; AL = AL MOD 10h
  2812 000037F8 D50A                <1>         aad 	; AX= AH*10+AL
  2813 000037FA A2[92690000]        <1> 	mov 	[hour], al
  2814 000037FF A0[93690000]        <1> 	mov 	al, [hour+1] ; Minute
  2815                              <1>         	; AL <= BCD number)
  2816 00003804 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2817                              <1> 					; AH = AL / 10h
  2818                              <1> 					; AL = AL MOD 10h
  2819 00003806 D50A                <1>         aad 	; AX= AH*10+AL
  2820 00003808 A2[94690000]        <1> 	mov 	[minute], al
  2821 0000380D A0[96690000]        <1> 	mov 	al, [second] ; Second
  2822                              <1>         	; AL <= BCD number)
  2823 00003812 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2824                              <1> 					; AH = AL / 10h
  2825                              <1> 					; AL = AL MOD 10h
  2826 00003814 D50A                <1>         aad 	; AX= AH*10+AL
  2827 00003816 A2[96690000]        <1> 	mov 	[second], al
  2828 0000381B 66A1[8C690000]      <1> 	mov 	ax, [year] ; Year (century)
  2829 00003821 6650                <1>         push 	ax
  2830                              <1> 	   	; AL <= BCD number)
  2831 00003823 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2832                              <1> 					; AH = AL / 10h
  2833                              <1> 					; AL = AL MOD 10h
  2834 00003825 D50A                <1>         aad 	; AX= AH*10+AL
  2835 00003827 B464                <1> 	mov 	ah, 100
  2836 00003829 F6E4                <1> 	mul 	ah
  2837 0000382B 66A3[8C690000]      <1> 	mov 	[year], ax
  2838 00003831 6658                <1> 	pop	ax
  2839 00003833 88E0                <1> 	mov	al, ah
  2840                              <1>         	; AL <= BCD number)
  2841 00003835 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2842                              <1> 					; AH = AL / 10h
  2843                              <1> 					; AL = AL MOD 10h
  2844 00003837 D50A                <1>         aad 	; AX= AH*10+AL
  2845 00003839 660105[8C690000]    <1> 	add 	[year], ax
  2846 00003840 A0[8E690000]        <1> 	mov 	al, [month] ; Month
  2847                              <1>            	; AL <= BCD number)
  2848 00003845 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2849                              <1> 					; AH = AL / 10h
  2850                              <1> 					; AL = AL MOD 10h
  2851 00003847 D50A                <1>         aad 	; AX= AH*10+AL
  2852 00003849 A2[8E690000]        <1> 	mov 	[month], al	
  2853 0000384E A0[8F690000]        <1>         mov     al, [month+1]      	; Day
  2854                              <1>            	; AL <= BCD number)
  2855 00003853 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2856                              <1> 					; AH = AL / 10h
  2857                              <1> 					; AL = AL MOD 10h
  2858 00003855 D50A                <1>         aad 	; AX= AH*10+AL
  2859 00003857 A2[90690000]        <1>         mov     [day], al
  2860                              <1> 	
  2861                              <1> convert_to_epoch:
  2862                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  2863                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  2864                              <1> 	;
  2865                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  2866                              <1> 	;
  2867                              <1> 	; Derived from DALLAS Semiconductor
  2868                              <1> 	; Application Note 31 (DS1602/DS1603)
  2869                              <1> 	; 6 May 1998
  2870 0000385C 29C0                <1> 	sub 	eax, eax
  2871 0000385E 66A1[8C690000]      <1> 	mov 	ax, [year]
  2872 00003864 662DB207            <1> 	sub 	ax, 1970
  2873 00003868 BA6D010000          <1> 	mov 	edx, 365
  2874 0000386D F7E2                <1> 	mul 	edx
  2875 0000386F 31DB                <1> 	xor 	ebx, ebx
  2876 00003871 8A1D[8E690000]      <1> 	mov 	bl, [month]
  2877 00003877 FECB                <1> 	dec 	bl
  2878 00003879 D0E3                <1> 	shl 	bl, 1
  2879                              <1> 	;sub	edx, edx
  2880 0000387B 668B93[98690000]    <1> 	mov 	dx, [EBX+DMonth]
  2881 00003882 8A1D[90690000]      <1>         mov     bl, [day]
  2882 00003888 FECB                <1> 	dec 	bl
  2883 0000388A 01D0                <1> 	add 	eax, edx
  2884 0000388C 01D8                <1> 	add 	eax, ebx
  2885                              <1> 			; EAX = days since 1/1/1970
  2886 0000388E 668B15[8C690000]    <1> 	mov 	dx, [year]
  2887 00003895 6681EAB107          <1> 	sub 	dx, 1969
  2888 0000389A 66D1EA              <1> 	shr 	dx, 1
  2889 0000389D 66D1EA              <1> 	shr 	dx, 1		
  2890                              <1> 		; (year-1969)/4
  2891 000038A0 01D0                <1> 	add 	eax, edx
  2892                              <1> 			; + leap days since 1/1/1970
  2893 000038A2 803D[8E690000]02    <1> 	cmp 	byte [month], 2	; if past february
  2894 000038A9 7610                <1> 	jna 	short cte1
  2895 000038AB 668B15[8C690000]    <1> 	mov 	dx, [year]
  2896 000038B2 6683E203            <1> 	and 	dx, 3 ; year mod 4
  2897 000038B6 7503                <1> 	jnz 	short cte1		
  2898                              <1> 			; and if leap year
  2899 000038B8 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  2900                              <1> cte1: 			; compute seconds since 1/1/1970
  2901 000038BB BA18000000          <1> 	mov 	edx, 24
  2902 000038C0 F7E2                <1> 	mul	edx
  2903 000038C2 8A15[92690000]      <1> 	mov 	dl, [hour]
  2904 000038C8 01D0                <1> 	add 	eax, edx
  2905                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  2906                              <1> 	;mov	ebx, 60
  2907 000038CA B33C                <1> 	mov	bl, 60
  2908 000038CC F7E3                <1> 	mul	ebx
  2909 000038CE 8A15[94690000]      <1> 	mov 	dl, [minute]
  2910 000038D4 01D0                <1> 	add 	eax, edx
  2911                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  2912                              <1> 	;mov 	ebx, 60
  2913 000038D6 F7E3                <1> 	mul	ebx
  2914 000038D8 8A15[96690000]      <1> 	mov 	dl, [second]
  2915 000038DE 01D0                <1> 	add 	eax, edx
  2916                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  2917 000038E0 C3                  <1> 	retn
  2918                              <1> 
  2919                              <1> get_rtc_time:
  2920                              <1> 	; 15/03/2015
  2921                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  2922                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  2923                              <1> 	; INT 1Ah
  2924                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  2925                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  2926                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  2927                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  2928                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  2929                              <1> 	;								
  2930                              <1> RTC_20: 				; GET RTC TIME
  2931 000038E1 FA                  <1> 	cli
  2932 000038E2 E819D3FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  2933 000038E7 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  2934                              <1> 
  2935 000038E9 B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  2936 000038EB E8FAD2FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  2937 000038F0 88C6                <1> 	MOV	DH, AL			; SAVE
  2938 000038F2 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  2939 000038F4 E8F1D2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  2940 000038F9 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  2941 000038FB 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  2942 000038FD B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  2943 000038FF E8E6D2FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  2944 00003904 88C1                <1> 	MOV	CL, AL			; SAVE
  2945 00003906 B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  2946 00003908 E8DDD2FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  2947 0000390D 88C5                <1> 	MOV	CH, AL			; SAVE
  2948 0000390F F8                  <1> 	CLC				; SET CY= 0
  2949                              <1> RTC_29:
  2950 00003910 FB                  <1> 	sti
  2951 00003911 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  2952                              <1> 
  2953                              <1> get_rtc_date:
  2954                              <1> 	; 15/03/2015
  2955                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  2956                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  2957                              <1> 	; INT 1Ah
  2958                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  2959                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  2960                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  2961                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  2962                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  2963                              <1> 	;
  2964                              <1> RTC_40: 				; GET RTC DATE
  2965 00003912 FA                  <1> 	cli
  2966 00003913 E8E8D2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  2967 00003918 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  2968                              <1> 
  2969 0000391A B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  2970 0000391C E8C9D2FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  2971 00003921 88C2                <1> 	MOV	DL, AL			; SAVE
  2972 00003923 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  2973 00003925 E8C0D2FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  2974 0000392A 88C6                <1> 	MOV	DH, AL			; SAVE
  2975 0000392C B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  2976 0000392E E8B7D2FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  2977 00003933 88C1                <1> 	MOV	CL, AL			; SAVE
  2978 00003935 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  2979 00003937 E8AED2FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  2980 0000393C 88C5                <1> 	MOV	CH, AL			; SAVE
  2981 0000393E F8                  <1> 	CLC				; SET CY=0
  2982                              <1> RTC_49:
  2983 0000393F FB                  <1> 	sti
  2984 00003940 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  2985                              <1> 
  2986                              <1> set_date_time:
  2987                              <1> convert_from_epoch:
  2988                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2989                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  2990                              <1> 	; 'convert_from_epoch' procedure prototype: 
  2991                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2992                              <1> 	;
  2993                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  2994                              <1> 	;
  2995                              <1> 	; Derived from DALLAS Semiconductor
  2996                              <1> 	; Application Note 31 (DS1602/DS1603)
  2997                              <1> 	; 6 May 1998
  2998                              <1> 	;
  2999                              <1> 	; INPUT:
  3000                              <1> 	; EAX = Unix (Epoch) Time
  3001                              <1> 	;
  3002 00003941 31D2                <1> 	xor 	edx, edx
  3003 00003943 B93C000000          <1> 	mov 	ecx, 60
  3004 00003948 F7F1                <1> 	div	ecx
  3005                              <1> 	;mov 	[imin], eax   ; whole minutes
  3006                              <1> 			  ; since 1/1/1970
  3007 0000394A 668915[96690000]    <1> 	mov 	[second], dx  ; leftover seconds
  3008 00003951 29D2                <1> 	sub 	edx, edx
  3009 00003953 F7F1                <1> 	div	ecx
  3010                              <1> 	;mov 	[ihrs], eax   ; whole hours
  3011                              <1> 	;		      ; since 1/1/1970
  3012 00003955 668915[94690000]    <1> 	mov 	[minute], dx  ; leftover minutes
  3013 0000395C 31D2                <1> 	xor	edx, edx
  3014                              <1> 	;mov 	cx, 24
  3015 0000395E B118                <1> 	mov 	cl, 24
  3016 00003960 F7F1                <1> 	div	ecx
  3017                              <1> 	;mov 	[iday], ax   ; whole days
  3018                              <1> 			     ; since 1/1/1970
  3019 00003962 668915[92690000]    <1> 	mov 	[hour], dx   ; leftover hours
  3020 00003969 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3021                              <1> 			     ; 1/1/1968 	
  3022                              <1> 	;mov 	[iday], ax
  3023 0000396E 50                  <1> 	push 	eax
  3024 0000396F 29D2                <1> 	sub	edx, edx
  3025 00003971 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3026 00003976 F7F1                <1> 	div	ecx
  3027 00003978 59                  <1> 	pop 	ecx
  3028                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3029 00003979 6652                <1> 	push 	dx
  3030                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3031 0000397B 6683FA3C            <1> 	cmp 	dx, 31 + 29  ; if past feb 29 then
  3032 0000397F F5                  <1> 	cmc		     ; add this quadyr's leap day
  3033 00003980 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3034                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3035                              <1> 	;mov 	cx, [iday]
  3036 00003983 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3037 00003984 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3038 00003986 B96D010000          <1> 	mov 	ecx, 365
  3039 0000398B 31D2                <1> 	xor	edx, edx
  3040                              <1> 	; EAX = iday-lday, EDX = 0
  3041 0000398D F7F1                <1> 	div	ecx
  3042                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3043                              <1> 	;jday = iday - (iyrs*365) - lday
  3044                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3045                              <1> 	;add	eax, 1968
  3046 0000398F 6605B007            <1> 	add 	ax, 1968     ; compute year
  3047 00003993 66A3[8C690000]      <1> 	mov 	[year], ax
  3048 00003999 6689D1              <1> 	mov 	cx, dx
  3049                              <1> 	;mov 	dx, [qday]
  3050 0000399C 665A                <1> 	pop 	dx
  3051 0000399E 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3052 000039A3 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3053 000039A5 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3054 000039A9 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3055 000039AA 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3056                              <1> cfe1:			
  3057                              <1> 	;mov 	[jday], cx
  3058 000039AE 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3059 000039B2 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3060 000039B6 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3061                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3062 000039BA 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3063 000039BD 731D                <1> 	jnb 	short cfe3
  3064 000039BF 664B                <1> 	dec 	bx           ; month = month - 1
  3065 000039C1 66D1E3              <1> 	shl 	bx, 1 
  3066 000039C4 668B93[98690000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3067 000039CB 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3068 000039CE 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3069 000039D2 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3070 000039D4 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3071 000039D6 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3072 000039D8 6642                <1> 	inc 	dx           ; mday = mday + 1
  3073 000039DA EBDE                <1> 	jmp 	short cfe2
  3074                              <1> cfe3:
  3075 000039DC 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3076 000039DE 66891D[8E690000]    <1> 	mov 	[month], bx
  3077 000039E5 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3078 000039E8 6641                <1> 	inc 	cx 			  
  3079 000039EA 66890D[90690000]    <1> 	mov 	[day], cx
  3080                              <1> 	
  3081                              <1> 	; eax, ebx, ecx, edx is changed at return
  3082                              <1> 	; output ->
  3083                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3084                              <1> 	
  3085                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3086                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3087                              <1> set_date:
  3088 000039F1 A0[8D690000]        <1>         mov     al, [year+1]
  3089 000039F6 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3090 000039F8 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3091                              <1> 			     ; AL = AH * 10h + AL
  3092 000039FA 88C5                <1> 	mov 	ch, al ; century (BCD)
  3093 000039FC A0[8C690000]        <1> 	mov 	al, [year]
  3094 00003A01 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3095 00003A03 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3096                              <1> 			     ; AL = AH * 10h + AL
  3097 00003A05 88C1                <1> 	mov 	cl, al ; year (BCD)
  3098 00003A07 A0[8E690000]        <1>         mov 	al, [month]
  3099 00003A0C D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3100 00003A0E D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3101                              <1> 			     ; AL = AH * 10h + AL
  3102 00003A10 88C6                <1> 	mov 	dh, al ; month (BCD)
  3103 00003A12 A0[90690000]        <1> 	mov 	al, [day]
  3104 00003A17 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3105 00003A19 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3106                              <1> 			     ; AL = AH * 10h + AL
  3107 00003A1B 88C6                <1> 	mov 	dh, al ; day (BCD)
  3108                              <1> 	; Set real-time clock date
  3109 00003A1D E879000000          <1> 	call	set_rtc_date
  3110                              <1> set_time:
  3111                              <1>         ; Read real-time clock time 
  3112                              <1> 	; (get day light saving time bit status)
  3113 00003A22 FA                  <1>  	cli
  3114 00003A23 E8D8D1FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3115                              <1> 	; cf = 1 -> al = 0
  3116 00003A28 7207                <1>         jc      short stime1
  3117 00003A2A B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3118 00003A2C E8B9D1FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3119                              <1> stime1:
  3120 00003A31 FB                  <1> 	sti
  3121 00003A32 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3122 00003A34 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3123                              <1> 	; DL = 1 or 0 (day light saving time)
  3124                              <1> 	;	
  3125 00003A36 A0[92690000]        <1> 	mov 	al, [hour]
  3126 00003A3B D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3127 00003A3D D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3128                              <1> 			     ; AL = AH * 10h + AL
  3129 00003A3F 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3130 00003A41 A0[94690000]        <1>         mov     al, [minute]
  3131 00003A46 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3132 00003A48 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3133                              <1> 			     ; AL = AH * 10h + AL
  3134 00003A4A 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3135 00003A4C A0[96690000]        <1>         mov     al, [second]
  3136 00003A51 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3137 00003A53 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3138                              <1> 			     ; AL = AH * 10h + AL
  3139 00003A55 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3140                              <1> 	; Set real-time clock time
  3141                              <1>  	; call	set_rtc_time
  3142                              <1> set_rtc_time:
  3143                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3144                              <1> 	; 15/03/2015
  3145                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3146                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3147                              <1> 	; INT 1Ah
  3148                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3149                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3150                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3151                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3152                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3153                              <1> 	;								:
  3154                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3155                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3156                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3157                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3158                              <1> 	;
  3159                              <1> RTC_30: 				; SET RTC TIME
  3160 00003A57 FA                  <1> 	cli
  3161 00003A58 E8A3D1FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3162 00003A5D 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3163 00003A5F E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3164                              <1> RTC_35:
  3165 00003A64 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3166 00003A66 B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3167 00003A68 E89E000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3168 00003A6D 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3169 00003A6F B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3170 00003A71 E895000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3171 00003A76 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3172 00003A78 B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3173 00003A7A E88C000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3174                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3175 00003A7F 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3176 00003A83 E862D1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3177 00003A88 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3178 00003A8A 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3179 00003A8C 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3180 00003A8F 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3181 00003A91 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3182 00003A93 E873000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3183 00003A98 F8                  <1> 	CLC				; SET CY= 0
  3184 00003A99 FB                  <1> 	sti
  3185 00003A9A C3                  <1> 	RETn				; RETURN WITH CY= 0
  3186                              <1> 
  3187                              <1> set_rtc_date:
  3188                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3189                              <1> 	; 15/03/2015
  3190                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3191                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3192                              <1> 	; INT 1Ah
  3193                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3194                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3195                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3196                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3197                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3198                              <1> 	;
  3199                              <1> RTC_50: 				; SET RTC DATE
  3200 00003A9B FA                  <1> 	cli
  3201 00003A9C E85FD1FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3202 00003AA1 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3203 00003AA3 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3204                              <1> RTC_55:
  3205 00003AA8 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3206 00003AAC E85A000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3207 00003AB1 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3208 00003AB3 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3209 00003AB5 E851000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3210 00003ABA 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3211 00003ABC B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3212 00003ABE E848000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3213 00003AC3 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3214 00003AC5 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3215 00003AC7 E83F000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3216 00003ACC 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3217 00003ACE B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3218 00003AD0 E836000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3219                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3220 00003AD5 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3221 00003AD9 E80CD1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3222 00003ADE 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3223 00003AE0 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3224 00003AE2 E824000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3225 00003AE7 F8                  <1> 	CLC				; SET CY= 0
  3226 00003AE8 FB                  <1> 	sti
  3227 00003AE9 C3                  <1> 	RETn				; RETURN CY=0
  3228                              <1> 
  3229                              <1> 	; 15/03/2015
  3230                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3231 00003AEA B426                <1> 	mov	ah, 26h
  3232 00003AEC B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3233 00003AEE E818000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3234 00003AF3 B482                <1> 	mov	ah, 82h
  3235 00003AF5 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3236 00003AF7 E80F000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3237 00003AFC B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3238 00003AFE E8E7D0FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3239 00003B03 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3240 00003B05 E8E0D0FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3241 00003B0A C3                  <1> 	RETn
  3242                              <1> 
  3243                              <1> 	; 15/03/2015
  3244                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3245                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3246 00003B0B 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3247                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3248 00003B0C D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3249 00003B0E F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3250 00003B0F D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3251 00003B11 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3252 00003B12 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3253 00003B14 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3254 00003B16 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3255 00003B18 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3256 00003B1A D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3257 00003B1C E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3258 00003B1E 90                  <1> 	nop			; I/O DELAY
  3259 00003B1F E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3260                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3261 00003B21 9D                  <1> 	popf	
  3262 00003B22 C3                  <1> 	RETn
  3263                              <1> 
  3264                              <1> bf_init:
  3265                              <1> 	; 14/08/2015
  3266                              <1> 	; 02/07/2015
  3267                              <1> 	; 01/07/2015
  3268                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3269                              <1> 	; Buffer (pointer) initialization !
  3270                              <1> 	; 
  3271                              <1> 	; 17/07/2013 - 24/07/2013
  3272                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3273                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3274                              <1> 	;
  3275 00003B23 BF[CA6F0000]        <1> 	mov	edi, bufp 
  3276 00003B28 B8[C07C0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3277 00003B2D 29D2                <1> 	sub	edx, edx
  3278 00003B2F FECA                <1> 	dec	dl
  3279 00003B31 31C9                <1> 	xor	ecx, ecx
  3280 00003B33 49                  <1> 	dec	ecx
  3281                              <1> bi0:
  3282 00003B34 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3283 00003B39 AB                  <1> 	stosd
  3284 00003B3A 89C6                <1> 	mov	esi, eax
  3285 00003B3C 8916                <1> 	mov	[esi], edx ; 000000FFh
  3286                              <1> 			    ; Not a valid device sign
  3287 00003B3E 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3288                              <1> 		      ; Not a valid block number sign 	 	
  3289 00003B41 3D[90700000]        <1> 	cmp	eax, buffer
  3290 00003B46 77EC                <1> 	ja	short bi0
  3291 00003B48 B8[C07C0000]        <1> 	mov	eax, sb0
  3292 00003B4D AB                  <1> 	stosd
  3293 00003B4E B8[C87E0000]        <1> 	mov	eax, sb1
  3294 00003B53 AB                  <1> 	stosd
  3295 00003B54 89C6                <1> 	mov	esi, eax ; offset sb1
  3296 00003B56 8916                <1> 	mov	[esi], edx ; 000000FFh
  3297                              <1> 			    ; Not a valid device sign
  3298 00003B58 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3299                              <1> 		      ; Not a valid block number sign 	 
  3300                              <1> 	; 14/08/2015
  3301                              <1> 	;call 	rdev_init
  3302                              <1> 	;retn
  3303                              <1> 
  3304                              <1> rdev_init: ; root device, super block buffer initialization
  3305                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3306                              <1> 	; 14/08/2015
  3307                              <1> 	; Retro UNIX 386 v1 feature only !
  3308                              <1> 	;
  3309                              <1> 	; NOTE: Disk partitions (file systems), logical
  3310                              <1> 	; drive initialization, partition's start sector etc.
  3311                              <1> 	; will be coded here, later in 'ldrv_init'	
  3312                              <1> 
  3313 00003B5B 0FB605[DA660000]    <1> 	movzx	eax, byte [boot_drv]
  3314                              <1> rdi_0:
  3315 00003B62 3C80                <1> 	cmp	al, 80h
  3316 00003B64 7202                <1> 	jb	short rdi_1
  3317 00003B66 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3318                              <1> rdi_1:
  3319 00003B68 A2[F06F0000]        <1> 	mov	[rdev], al
  3320 00003B6D BB[C07C0000]        <1>         mov	ebx, sb0 ; super block buffer
  3321 00003B72 8903                <1> 	mov 	[ebx], eax
  3322 00003B74 B001                <1> 	mov	al, 1 ; eax = 1
  3323 00003B76 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3324                              <1> 	;call 	diskio
  3325                              <1> 	;retn
  3326                              <1> 	; 24/12/2021
  3327 00003B79 E9BE230000          <1> 	jmp	diskio
  3328                              <1> 
  3329                              <1> ; 23/10/2015
  3330                              <1> com1_irq4:
  3331 00003B7E [863B0000]          <1> 	dd dummy_retn
  3332                              <1> com2_irq3:
  3333 00003B82 [863B0000]          <1> 	dd dummy_retn
  3334                              <1> 
  3335                              <1> dummy_retn:
  3336 00003B86 C3                  <1> 	retn
  1993                                  %include 'u1.s'        ; 10/05/2015
  1994                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS1.INC
  1995                              <1> ; Last Modification: 24/12/2021
  1996                              <1> ; ----------------------------------------------------------------------------
  1997                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1998                              <1> ; (v0.1 - Beginning: 11/07/2012)
  1999                              <1> ;
  2000                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2001                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2002                              <1> ; <Bell Laboratories (17/3/1972)>
  2003                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2004                              <1> ;
  2005                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2006                              <1> ;
  2007                              <1> ; ****************************************************************************
  2008                              <1> 
  2009                              <1> unkni: ; / used for all system calls
  2010                              <1> sysent: ; < enter to system call >
  2011                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2012                              <1> 	; 19/10/2015
  2013                              <1> 	; 21/09/2015
  2014                              <1> 	; 01/07/2015
  2015                              <1> 	; 19/05/2015
  2016                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2017                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2018                              <1> 	;
  2019                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2020                              <1> 	; The trap type is determined and an indirect jump is made to 
  2021                              <1> 	; the appropriate system call handler. If there is a trap inside
  2022                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2023                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2024                              <1> 	; instructor is decoded to get the the system code part (see
  2025                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2026                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2027                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2028                              <1> 	; is called. If the call is legitimate control passes to the
  2029                              <1> 	; appropriate system routine.
  2030                              <1> 	;
  2031                              <1> 	; Calling sequence:
  2032                              <1> 	;	Through a trap caused by any sys call outside the system.
  2033                              <1> 	; Arguments:
  2034                              <1> 	;	Arguments of particular system call.	
  2035                              <1> 	; ...............................................................
  2036                              <1> 	;	
  2037                              <1> 	; Retro UNIX 8086 v1 modification: 
  2038                              <1> 	;       System call number is in EAX register.
  2039                              <1> 	;
  2040                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2041                              <1> 	;	registers depending of function details.
  2042                              <1>   	;
  2043                              <1> 	; 16/04/2015
  2044 00003B87 368925[00700000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2045                              <1> 	; save user registers
  2046 00003B8E 1E                  <1> 	push	ds
  2047 00003B8F 06                  <1> 	push	es
  2048 00003B90 0FA0                <1> 	push	fs
  2049 00003B92 0FA8                <1> 	push	gs
  2050 00003B94 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2051                              <1> 	;
  2052                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2053                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2054                              <1> 	;	for saving/restoring user registers.)
  2055                              <1> 	;
  2056 00003B95 50                  <1> 	push	eax ; 01/07/2015
  2057 00003B96 66B81000            <1> 	mov     ax, KDATA
  2058 00003B9A 8ED8                <1>         mov     ds, ax
  2059 00003B9C 8EC0                <1>         mov     es, ax
  2060 00003B9E 8EE0                <1>         mov     fs, ax
  2061 00003BA0 8EE8                <1>         mov     gs, ax
  2062 00003BA2 A1[286C0000]        <1> 	mov	eax, [k_page_dir]
  2063 00003BA7 0F22D8              <1> 	mov	cr3, eax
  2064 00003BAA 58                  <1> 	pop	eax ; 01/07/2015
  2065                              <1> 	; 19/10/2015
  2066 00003BAB FC                  <1> 	cld
  2067                              <1> 	;
  2068 00003BAC FE05[FF6F0000]      <1> 	inc	byte [sysflg]
  2069                              <1> 		; incb sysflg / indicate a system routine is in progress
  2070 00003BB2 FB                  <1>         sti 	; 18/01/2014
  2071                              <1> 	;jnz	panic ; 24/05/2013
  2072                              <1> 	; 24/12/2021
  2073 00003BB3 7405                <1> 	jz	short _1
  2074 00003BB5 E963F9FFFF          <1> 	jmp	panic
  2075                              <1> 		; beq 1f
  2076                              <1> 		; jmp panic ; / called if trap inside system
  2077                              <1> ;1:
  2078                              <1> _1:	; 24/12/2021
  2079                              <1> 	; 16/04/2015
  2080 00003BBA A3[08700000]        <1> 	mov	[u.r0], eax
  2081 00003BBF 8925[04700000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2082                              <1> 	;
  2083                              <1> 		; mov $s.syst+2,clockp
  2084                              <1> 		; mov r0,-(sp) / save user registers 
  2085                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2086                              <1> 			   ; / in u.r0
  2087                              <1> 		; mov r1,-(sp)
  2088                              <1> 		; mov r2,-(sp)
  2089                              <1> 		; mov r3,-(sp)
  2090                              <1> 		; mov r4,-(sp)
  2091                              <1> 		; mov r5,-(sp)
  2092                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2093                              <1> 		             ; / arithmetic unit
  2094                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2095                              <1> 		             ; / extended arithmetic unit
  2096                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2097                              <1> 		             ; / arithmetic unit
  2098                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2099                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2100                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2101                              <1> 		; sub $sys,r0 / get xxx code
  2102 00003BC5 C1E002              <1> 	shl	eax, 2
  2103                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2104 00003BC8 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2105                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2106                              <1> 	;jnb	short badsys
  2107                              <1> 		; bhis badsys / yes, bad system call
  2108 00003BCD F5                  <1> 	cmc
  2109 00003BCE 9C                  <1> 	pushf	
  2110 00003BCF 50                  <1> 	push	eax
  2111 00003BD0 8B2D[00700000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2112 00003BD6 B0FE                <1> 	mov	al, 0FEh ; 11111110b
  2113 00003BD8 1400                <1> 	adc	al, 0 ; al = al + cf
  2114 00003BDA 204508              <1> 	and	[ebp+8], al ; flags (reset carry flag)
  2115                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2116                              <1> 				 ; / and clear carry bit
  2117 00003BDD 5D                  <1> 	pop	ebp ; eax
  2118 00003BDE 9D                  <1> 	popf
  2119                              <1>         ;jc	badsys
  2120                              <1> 	; 24/12/2021
  2121 00003BDF 7305                <1> 	jnc	short _2
  2122 00003BE1 E951010000          <1> 	jmp	badsys
  2123                              <1> _2:
  2124 00003BE6 A1[08700000]        <1> 	mov	eax, [u.r0]
  2125                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2126 00003BEB FFA5[F13B0000]      <1> 	jmp	dword [ebp+syscalls]
  2127                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2128                              <1> 		            ; / to proper system routine.
  2129                              <1> syscalls: ; 1:
  2130                              <1> 	; 21/09/2015
  2131                              <1> 	; 01/07/2015
  2132                              <1> 	; 16/04/2015 (32 bit address modification) 
  2133 00003BF1 [013D0000]          <1> 	dd sysrele	; / 0
  2134 00003BF5 [A93D0000]          <1> 	dd sysexit 	; / 1
  2135 00003BF9 [CD3E0000]          <1> 	dd sysfork 	; / 2
  2136 00003BFD [E03F0000]          <1> 	dd sysread 	; / 3
  2137 00003C01 [F33F0000]          <1> 	dd syswrite 	; / 4
  2138 00003C05 [5C400000]          <1> 	dd sysopen 	; / 5
  2139 00003C09 [8C410000]          <1> 	dd sysclose 	; / 6
  2140 00003C0D [4F3E0000]          <1> 	dd syswait 	; / 7
  2141 00003C11 [06410000]          <1> 	dd syscreat 	; / 8
  2142 00003C15 [9D440000]          <1> 	dd syslink 	; / 9
  2143 00003C19 [5B450000]          <1> 	dd sysunlink 	; / 10
  2144 00003C1D [25460000]          <1> 	dd sysexec 	; / 11
  2145 00003C21 [664C0000]          <1> 	dd syschdir 	; / 12
  2146 00003C25 [4A4D0000]          <1> 	dd systime 	; / 13
  2147 00003C29 [45410000]          <1> 	dd sysmkdir 	; / 14
  2148 00003C2D [B84C0000]          <1> 	dd syschmod 	; / 15
  2149 00003C31 [1A4D0000]          <1> 	dd syschown 	; / 16
  2150 00003C35 [7D4D0000]          <1> 	dd sysbreak 	; / 17
  2151 00003C39 [E9490000]          <1> 	dd sysstat 	; / 18
  2152 00003C3D [3F4E0000]          <1> 	dd sysseek 	; / 19
  2153 00003C41 [514E0000]          <1> 	dd systell 	; / 20
  2154 00003C45 [2A590000]          <1> 	dd sysmount 	; / 21
  2155 00003C49 [DC590000]          <1> 	dd sysumount 	; / 22
  2156 00003C4D [CE4E0000]          <1> 	dd syssetuid 	; / 23
  2157 00003C51 [FF4E0000]          <1> 	dd sysgetuid 	; / 24
  2158 00003C55 [594D0000]          <1> 	dd sysstime 	; / 25
  2159 00003C59 [C24E0000]          <1> 	dd sysquit 	; / 26
  2160 00003C5D [B64E0000]          <1> 	dd sysintr 	; / 27
  2161 00003C61 [C5490000]          <1> 	dd sysfstat 	; / 28
  2162 00003C65 [A9410000]          <1> 	dd sysemt 	; / 29
  2163 00003C69 [D6410000]          <1> 	dd sysmdate 	; / 30
  2164 00003C6D [22420000]          <1> 	dd sysstty 	; / 31
  2165 00003C71 [90430000]          <1> 	dd sysgtty 	; / 32
  2166 00003C75 [D1410000]          <1> 	dd sysilgins 	; / 33
  2167 00003C79 [01620000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2168                              <1> 			     ; 11/06/2014
  2169 00003C7D [2E620000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2170                              <1> 			     ; 01/07/2015
  2171 00003C81 [06630000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2172                              <1> 			     ; 21/09/2015 - get last error number
  2173                              <1> end_of_syscalls:
  2174                              <1> 
  2175                              <1> error:
  2176                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2177                              <1> 	; 17/09/2015
  2178                              <1> 	; 03/09/2015
  2179                              <1> 	; 01/09/2015
  2180                              <1> 	; 09/06/2015
  2181                              <1> 	; 13/05/2015
  2182                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2183                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2184                              <1> 	;
  2185                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2186                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2187                              <1> 	;
  2188                              <1> 	; INPUTS -> none
  2189                              <1> 	; OUTPUTS ->
  2190                              <1> 	;	processor status - carry (c) bit is set (means error)
  2191                              <1> 	;
  2192                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2193                              <1> 	; 	      Because, jumps to error procedure
  2194                              <1> 	;	      disrupts push-pop nesting balance)
  2195                              <1> 	;
  2196 00003C85 8B2D[00700000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2197 00003C8B 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2198                              <1> 				 ; (system call will return with cf = 1)
  2199                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2200                              <1> 		               ; / users stack
  2201                              <1> 	; 17/09/2015
  2202 00003C8F 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2203                              <1> 				 ; for saving/restoring user registers	
  2204                              <1> 	;cmp	ebp, [u.usp]
  2205                              <1> 	;je	short err0	
  2206 00003C92 892D[04700000]      <1> 	mov	[u.usp], ebp
  2207                              <1> ;err0:
  2208                              <1> 	; 01/09/2015
  2209 00003C98 8B25[04700000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2210                              <1> 				    ; 10/04/2013
  2211                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2212                              <1> 				    ; related procedures will jump to 'error'
  2213                              <1> 				    ; procedure directly without returning to 
  2214                              <1> 				    ; the caller procedure. So, stack pointer
  2215                              <1>                                     ; must be restored here.)
  2216                              <1> 	; 13/05/2015
  2217                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2218                              <1> 	;	'get last error' system call later. 	
  2219                              <1> 
  2220                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2221 00003C9E C605[6F700000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2222                              <1> 
  2223                              <1> sysret: ; < return from system call>
  2224                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2225                              <1> 	; 10/09/2015
  2226                              <1> 	; 29/07/2015
  2227                              <1> 	; 25/06/2015
  2228                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2229                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2230                              <1> 	;
  2231                              <1> 	; 'sysret' first checks to see if process is about to be 
  2232                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2233                              <1> 	; If not, following happens:	 
  2234                              <1> 	; 	1) The user's stack pointer is restored.
  2235                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2236                              <1> 	;	   i-node has been modified. If it has, it is written out
  2237                              <1> 	;	   via 'ppoke'.
  2238                              <1> 	;	3) If the super block has been modified, it is written out
  2239                              <1> 	;	   via 'ppoke'.				
  2240                              <1> 	;	4) If the dismountable file system's super block has been
  2241                              <1> 	;	   modified, it is written out to the specified device
  2242                              <1> 	;	   via 'ppoke'.
  2243                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2244                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2245                              <1> 	;	   another user a chance to run.
  2246                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2247                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2248                              <1> 	;
  2249                              <1> 	; Calling sequence:
  2250                              <1> 	;	jump table or 'br sysret'
  2251                              <1> 	; Arguments: 
  2252                              <1> 	;	-	
  2253                              <1> 	; ...............................................................
  2254                              <1> 	;	
  2255                              <1> 	; ((AX=r1 for 'iget' input))
  2256                              <1> 	;	
  2257                              <1> 	;xor	ax, ax ; 04/05/2013
  2258                              <1> 	; 24/12/2021
  2259 00003CA5 31C0                <1> 	xor	eax, eax
  2260                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2261 00003CA7 FEC0                <1> 	inc	al ; 04/05/2013
  2262 00003CA9 3805[56700000]      <1> 	cmp	[u.bsys], al ; 1
  2263                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2264                              <1> 	;jnb	sysexit ; 04/05/2013
  2265                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2266                              <1> 	; 24/12/2021
  2267 00003CAF 720F                <1> 	jb	short _3
  2268 00003CB1 C705[5D700000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2268 00003CB9 0000                <1>
  2269 00003CBB E9E9000000          <1> 	jmp	sysexit
  2270                              <1> _3:
  2271                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2272                              <1> 		; mov u.sp,sp / no point stack to users stack
  2273 00003CC0 FEC8                <1> 	dec 	al ; mov ax, 0
  2274                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2275 00003CC2 E805160000          <1> 	call	iget
  2276                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2277                              <1> 		            ; / it is written out
  2278                              <1> 	;xor 	ax, ax ; 0
  2279                              <1> 	; 24/12/2021
  2280 00003CC7 31C0                <1> 	xor	eax, eax
  2281 00003CC9 3805[FD6F0000]      <1> 	cmp	[smod], al ; 0
  2282                              <1> 		; tstb	smod / has the super block been modified
  2283 00003CCF 7614                <1> 	jna	short sysret1
  2284                              <1> 		; beq	1f / no, 1f
  2285 00003CD1 A2[FD6F0000]        <1> 	mov	[smod], al ; 0
  2286                              <1> 		; clrb smod / yes, clear smod
  2287 00003CD6 BB[C07C0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2288 00003CDB 66810B0002          <1>    	or	word [ebx], 200h ;;
  2289                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2290                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2291                              <1> 		      	      ; / output
  2292                              <1> 	; AX = 0
  2293 00003CE0 E83E210000          <1> 	call 	poke ; 07/08/2013
  2294                              <1> 	; call	ppoke
  2295                              <1> 	; AX = 0
  2296                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2297                              <1> sysret1: ;1:
  2298 00003CE5 3805[FE6F0000]      <1> 	cmp	[mmod], al ; 0
  2299                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2300                              <1> 		           ; / system
  2301 00003CEB 7614                <1> 	jna	short sysrel0
  2302                              <1> 		; beq 1f / been modified?  no, 1f
  2303 00003CED A2[FE6F0000]        <1> 	mov	[mmod], al ; 0	
  2304                              <1> 		; clrb	mmod / yes, clear mmod
  2305                              <1>         ;mov    ax, [mntd]
  2306                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2307 00003CF2 BB[C87E0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2308                              <1>         ;;mov	[ebx], al
  2309                              <1> 	;mov    [sb1], al
  2310                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2311 00003CF7 66810B0002          <1> 	or	word [ebx], 200h
  2312                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2313                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2314 00003CFC E822210000          <1> 	call	poke ; 07/08/2013
  2315                              <1> 	;call	ppoke 
  2316                              <1> 		; jsr r0,ppoke / write it out to its device
  2317                              <1>         ;xor    al, al ; 26/04/2013       
  2318                              <1> ;1:
  2319                              <1> 		; tstb uquant / is the time quantum 0?
  2320                              <1> 		; bne 1f / no, don't swap it out
  2321                              <1> 
  2322                              <1> sysrele: ; < release >
  2323                              <1> 	; 14/10/2015
  2324                              <1> 	; 01/09/2015
  2325                              <1> 	; 24/07/2015
  2326                              <1> 	; 14/05/2015
  2327                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2328                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2329                              <1> 	;
  2330                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2331                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2332                              <1> 	; turns off the system flag. It then checked to see if there is
  2333                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2334                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2335                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2336                              <1> 	; the user, a rti is made.
  2337                              <1> 	;
  2338                              <1> 	; Calling sequence:
  2339                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2340                              <1> 	; Arguments:
  2341                              <1> 	;	-	
  2342                              <1> 	; ...............................................................
  2343                              <1> 	;	
  2344                              <1> 	; 23/02/2014 (swapret)
  2345                              <1> 	; 22/09/2013
  2346                              <1> sysrel0: ;1:
  2347 00003D01 803D[4A700000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2348                              <1> 		; tstb uquant / is the time quantum 0?
  2349 00003D08 7705                <1>         ja      short swapret
  2350                              <1> 		; bne 1f / no, don't swap it out
  2351                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2352 00003D0A E842120000          <1> 	call	tswap
  2353                              <1> 		; jsr r0,tswap / yes, swap it out
  2354                              <1> ;
  2355                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2356                              <1> swapret: ;1:
  2357                              <1> 	; 10/09/2015
  2358                              <1> 	; 01/09/2015
  2359                              <1> 	; 14/05/2015
  2360                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2361                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2362                              <1> 	; cli
  2363                              <1> 	; 24/07/2015
  2364                              <1> 	;
  2365                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2366                              <1> 	;; mov	esp, [u.usp]
  2367                              <1> 
  2368                              <1> 	; 22/09/2013
  2369 00003D0F E822140000          <1> 	call	isintr
  2370                              <1> 	; 20/10/2013
  2371 00003D14 7405                <1> 	jz	short sysrel1
  2372 00003D16 E877000000          <1> 	call	intract
  2373                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2374                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2375                              <1> 		               ; / action
  2376                              <1> sysrel1:
  2377 00003D1B FA                  <1> 	cli ; 14/10/2015
  2378 00003D1C FE0D[FF6F0000]      <1> 	dec	byte [sysflg]
  2379                              <1> 		; decb sysflg / turn system flag off
  2380 00003D22 A1[61700000]        <1> 	mov     eax, [u.pgdir]
  2381 00003D27 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2382                              <1> 			  ; (others are different than kernel page tables) 
  2383                              <1> 	; 10/09/2015
  2384 00003D2A 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2385                              <1> 		; mov (sp)+,sc / restore user registers
  2386                              <1> 		; mov (sp)+,mq
  2387                              <1> 		; mov (sp)+,ac
  2388                              <1> 		; mov (sp)+,r5
  2389                              <1> 		; mov (sp)+,r4
  2390                              <1> 		; mov (sp)+,r3
  2391                              <1> 		; mov (sp)+,r2
  2392                              <1> 	;
  2393 00003D2B A1[08700000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2394 00003D30 0FA9                <1> 	pop	gs
  2395 00003D32 0FA1                <1> 	pop	fs
  2396 00003D34 07                  <1> 	pop	es
  2397 00003D35 1F                  <1> 	pop	ds
  2398 00003D36 CF                  <1> 	iretd	
  2399                              <1> 		; rti / no, return from interrupt
  2400                              <1> 
  2401                              <1> badsys:
  2402                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2403                              <1> 	; (Major Modification: 'core' dumping procedure in
  2404                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2405                              <1> 	;	has been changed to print 'Invalid System Call !'
  2406                              <1> 	;	message on the user's console tty.)
  2407                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2408                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2409                              <1> 	; (EAX = Function number)  
  2410                              <1> 	;
  2411 00003D37 FE05[56700000]      <1> 	inc	byte [u.bsys]
  2412                              <1> 	;
  2413 00003D3D 8B1D[00700000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2414 00003D43 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2415 00003D45 E82CDBFFFF          <1> 	call	dwordtohex
  2416 00003D4A 8915[80690000]      <1> 	mov	[bsys_msg_eip], edx
  2417 00003D50 A3[84690000]        <1> 	mov	[bsys_msg_eip+4], eax
  2418 00003D55 A1[08700000]        <1> 	mov	eax, [u.r0]
  2419 00003D5A E817DBFFFF          <1> 	call	dwordtohex
  2420 00003D5F 8915[70690000]      <1> 	mov	[bsys_msg_eax], edx
  2421 00003D65 A3[74690000]        <1> 	mov	[bsys_msg_eax+4], eax
  2422                              <1> 	; 24/12/2021
  2423                              <1> 	;xor	eax, eax
  2424                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2425                              <1> 	;mov	ebx, [u.fofp]
  2426                              <1> 	;mov	[ebx], eax
  2427                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2428                              <1> 	;inc	eax
  2429                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2430                              <1> 		; writei
  2431                              <1> 		; INPUTS ->
  2432                              <1> 		;    r1 - inode number
  2433                              <1> 		;    u.count - byte count to be written
  2434                              <1> 		;    u.base - points to user buffer
  2435                              <1> 		;    u.fofp - points to word with current file offset
  2436                              <1> 		; OUTPUTS ->
  2437                              <1> 		;    u.count - cleared
  2438                              <1> 		;    u.nread - accumulates total bytes passed back	
  2439                              <1> 		;
  2440                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2441                              <1> 	;call	writei
  2442                              <1> 	;;mov	eax, 1
  2443                              <1> 	;jmp	sysexit
  2444                              <1> 
  2445                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2446 00003D6A BE[51690000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2447 00003D6F 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2448 00003D76 8A83[556D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2449 00003D7C C605[576C0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2450 00003D83 A2[5C700000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2451 00003D88 E85E250000          <1> 	call	print_cmsg
  2452                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2453 00003D8D E9F3FEFFFF          <1> 	jmp	error
  2454                              <1> 
  2455                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2456                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2457                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2458                              <1> 		; br 1f / error
  2459                              <1> 		; neg r1 / negate the i-number to open the core image file
  2460                              <1> 		       ; / for writing
  2461                              <1> 		; jsr r0,iopen / open the core image file
  2462                              <1> 		; jsr r0,itrunc / free all associated blocks
  2463                              <1> 		; br 2f
  2464                              <1> ;1:
  2465                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2466                              <1> 		; jsr r0,maknod / make an i-node
  2467                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2468                              <1> ;2:
  2469                              <1> 		; mov $core,u.base / move address core to u.base
  2470                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2471                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2472                              <1> 		; clr u.off / clear user offset
  2473                              <1> 		; jsr r0,writei / write out the core image to the user
  2474                              <1> 		; mov $user,u.base / pt. u.base to user
  2475                              <1> 		; mov $64.,u.count / u.count = 64
  2476                              <1> 		; jsr r0,writei / write out all the user parameters
  2477                              <1> 		; neg r1 / make i-number positive
  2478                              <1> 		; jsr r0,iclose / close the core image file
  2479                              <1> 		; br sysexit /
  2480                              <1> ;3:
  2481                              <1> 		; <core\0\0>
  2482                              <1> 
  2483                              <1> intract: ; / interrupt action
  2484                              <1> 	; 14/10/2015
  2485                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2486                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2487                              <1> 	;
  2488                              <1> 	; Retro UNIX 8086 v1 modification !
  2489                              <1> 	; (Process/task switching and quit routine by using
  2490                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2491                              <1> 	;
  2492                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2493                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2494                              <1> 	;		'intract' will jump to 'sysexit'.
  2495                              <1> 	;	    Intract will return to the caller 
  2496                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2497                              <1> 	; 14/10/2015
  2498 00003D92 FB                  <1> 	sti
  2499                              <1> 	; 07/12/2013	
  2500 00003D93 66FF05[4E700000]    <1> 	inc 	word [u.quit]
  2501 00003D9A 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2502 00003D9C 66FF0D[4E700000]    <1> 	dec	word [u.quit]
  2503                              <1> 	; 16/04/2015
  2504 00003DA3 C3                  <1> 	retn
  2505                              <1> intrct0:	
  2506 00003DA4 58                  <1> 	pop	eax ; call intract -> retn
  2507                              <1> 	;
  2508 00003DA5 31C0                <1> 	xor 	eax, eax
  2509 00003DA7 FEC0                <1> 	inc	al  ; mov ax, 1
  2510                              <1> ;;;
  2511                              <1> 	; UNIX v1 original 'intract' routine... 
  2512                              <1> 	; / interrupt action
  2513                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2514                              <1> 		; bne 1f / no, 1f
  2515                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2516                              <1> 	; 1: / now in user area
  2517                              <1> 		; mov r1,-(sp) / save r1
  2518                              <1> 		; mov u.ttyp,r1 
  2519                              <1> 			; / pointer to tty buffer in control-to r1
  2520                              <1> 		; cmpb 6(r1),$177
  2521                              <1> 			; / is the interrupt char equal to "del"
  2522                              <1> 		; beq 1f / yes, 1f
  2523                              <1> 		; clrb 6(r1) 
  2524                              <1> 		        ; / no, clear the byte 
  2525                              <1> 			; / (must be a quit character)
  2526                              <1> 		; mov (sp)+,r1 / restore r1
  2527                              <1> 		; clr u.quit / clear quit flag
  2528                              <1> 		; bis $20,2(sp) 
  2529                              <1> 		    	; / set trace for quit (sets t bit of 
  2530                              <1> 			; / ps-trace trap)
  2531                              <1> 		; rti   ;  / return from interrupt
  2532                              <1> 	; 1: / interrupt char = del
  2533                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2534                              <1> 			   ; / in the buffer
  2535                              <1> 		; mov (sp)+,r1 / restore r1
  2536                              <1> 		; cmp u.intr,$core / should control be 
  2537                              <1> 				; / transferred to loc core?
  2538                              <1> 		; blo 1f
  2539                              <1> 		; jmp *u.intr / user to do rti yes, 
  2540                              <1> 				; / transfer to loc core
  2541                              <1> 	; 1:
  2542                              <1> 		; sys 1 / exit
  2543                              <1> 
  2544                              <1> sysexit: ; <terminate process>
  2545                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2546                              <1> 	; 01/09/2015
  2547                              <1> 	; 31/08/2015
  2548                              <1> 	; 14/05/2015
  2549                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2550                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2551                              <1> 	;
  2552                              <1> 	; 'sysexit' terminates a process. First each file that
  2553                              <1> 	; the process has opened is closed by 'flose'. The process
  2554                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2555                              <1> 	; searched to find children of the dying process. If any of
  2556                              <1> 	; children are zombies (died by not waited for), they are
  2557                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2558                              <1> 	; dying process's parent. When the parent is found, it is
  2559                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2560                              <1> 	; one of these, the dying process just dies. If it is waiting
  2561                              <1> 	; for a child process to die, it notified that it doesn't 
  2562                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2563                              <1> 	; (waiting to active). It is awakened and put on runq by
  2564                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2565                              <1> 	; it will never be run again but stays around until a 'wait'
  2566                              <1> 	; is completed by it's parent process. If the parent is not
  2567                              <1> 	; found, process just dies. This means 'swap' is called with
  2568                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2569                              <1> 	; to write out the process and 'rswap' reads the new process
  2570                              <1> 	; over the one that dies..i.e., the dying process is 
  2571                              <1> 	; overwritten and destroyed.	
  2572                              <1>  	;
  2573                              <1> 	; Calling sequence:
  2574                              <1> 	;	sysexit or conditional branch.
  2575                              <1> 	; Arguments:
  2576                              <1> 	;	-	
  2577                              <1> 	; ...............................................................
  2578                              <1> 	;	
  2579                              <1> 	; Retro UNIX 8086 v1 modification: 
  2580                              <1> 	;       System call number (=1) is in EAX register.
  2581                              <1> 	;
  2582                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2583                              <1> 	;       registers depending of function details.
  2584                              <1> 	;
  2585                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2586                              <1> 	;
  2587                              <1> ; / terminate process
  2588                              <1> 	; AX = 1
  2589                              <1> 	;dec 	ax ; 0
  2590                              <1> 	; 24/12/2021
  2591 00003DA9 48                  <1> 	dec	eax ; 0
  2592                              <1> 	;dec 	ax ; 0
  2593 00003DAA 66A3[4C700000]      <1> 	mov	[u.intr], ax ; 0
  2594                              <1> 		; clr u.intr / clear interrupt control word
  2595                              <1> 		; clr r1 / clear r1
  2596                              <1> 	; AX = 0
  2597                              <1> sysexit_1: ; 1:
  2598                              <1> 	; AX = File descriptor
  2599                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2600                              <1> 		; / Search the whole list
  2601 00003DB0 E8C70C0000          <1> 	call	fclose
  2602                              <1> 		; jsr r0,fclose / close all files the process opened
  2603                              <1> 	;; ignore error return
  2604                              <1> 		; br .+2 / ignore error return
  2605                              <1> 	;inc	ax
  2606 00003DB5 FEC0                <1> 	inc	al
  2607                              <1> 		; inc r1 / increment file descriptor
  2608                              <1> 	;cmp	ax, 10
  2609 00003DB7 3C0A                <1> 	cmp	al, 10
  2610                              <1> 		; cmp r1,$10. / end of u.fp list?
  2611 00003DB9 72F5                <1> 	jb	short sysexit_1
  2612                              <1> 		; blt 1b / no, go back
  2613 00003DBB 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2614                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2615 00003DC2 88A3[856D0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2616                              <1> 		; clrb p.stat-1(r1) / free the process
  2617                              <1> 	;shl	bx, 1
  2618 00003DC8 D0E3                <1> 	shl	bl, 1
  2619                              <1> 		; asl r1 / use r1 for index into the below tables
  2620 00003DCA 668B8B[F46C0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2621                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2622 00003DD1 668B93[146D0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2623                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2624                              <1> 	; xor 	bx, bx ; 0
  2625 00003DD8 30DB                <1> 	xor	bl, bl ; 0
  2626                              <1> 		; clr r2
  2627 00003DDA 31F6                <1> 	xor	esi, esi ; 0
  2628                              <1> 		; clr r5 / initialize reg
  2629                              <1> sysexit_2: ; 1:
  2630                              <1> 	        ; / find children of this dying process, 
  2631                              <1> 		; / if they are zombies, free them
  2632                              <1> 	;add	bx, 2
  2633 00003DDC 80C302              <1> 	add	bl, 2
  2634                              <1> 		; add $2,r2 / search parent process table 
  2635                              <1> 		          ; / for dying process's name
  2636 00003DDF 66398B[146D0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2637                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2638 00003DE6 7513                <1> 	jne	short sysexit_4
  2639                              <1> 		; bne 3f / no
  2640                              <1> 	;shr	bx, 1
  2641 00003DE8 D0EB                <1> 	shr	bl, 1
  2642                              <1> 		; asr r2 / yes, it is a parent
  2643 00003DEA 80BB[856D0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2644                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2645                              <1> 				     ; / dying process a zombie
  2646 00003DF1 7506                <1> 	jne	short sysexit_3 
  2647                              <1> 		; bne 2f / no
  2648 00003DF3 88A3[856D0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2649                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2650                              <1> sysexit_3: ; 2:
  2651                              <1> 	;shr	bx, 1
  2652 00003DF9 D0E3                <1> 	shl	bl, 1
  2653                              <1> 		; asl r2
  2654                              <1> sysexit_4: ; 3:
  2655                              <1> 		; / search the process name table 
  2656                              <1> 		; / for the dying process's parent
  2657 00003DFB 663993[F46C0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2658                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2659 00003E02 7502                <1> 	jne	short sysexit_5
  2660                              <1> 		; bne 3f / no
  2661 00003E04 89DE                <1> 	mov	esi, ebx
  2662                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2663                              <1> 		          ; / process # x2) in r5
  2664                              <1> sysexit_5: ; 3:
  2665                              <1> 	;cmp	bx, nproc + nproc
  2666 00003E06 80FB20              <1> 	cmp	bl, nproc + nproc
  2667                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2668 00003E09 72D1                <1> 	jb	short sysexit_2
  2669                              <1> 		; blt 1b / no, go back
  2670                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2671 00003E0B 21F6                <1> 	and	esi, esi ; r5=r1
  2672 00003E0D 7431                <1> 	jz	short sysexit_6
  2673                              <1> 		; beq 2f / no parent has been found. 
  2674                              <1> 		       ; / The process just dies
  2675 00003E0F 66D1EE              <1> 	shr	si, 1
  2676                              <1> 		; asr r1 / set up index to p.stat
  2677 00003E12 8A86[856D0000]      <1> 	mov	al, [esi+p.stat-1]
  2678                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2679 00003E18 20C0                <1> 	and	al, al
  2680 00003E1A 7424                <1> 	jz	short sysexit_6
  2681                              <1> 		; beq 2f / if its been freed, 2f
  2682 00003E1C 3C03                <1> 	cmp	al, 3
  2683                              <1> 		; cmp r2,$3 / is parent a zombie?
  2684 00003E1E 7420                <1> 	je	short sysexit_6
  2685                              <1> 		; beq 2f / yes, 2f
  2686                              <1> 	; BH = 0
  2687 00003E20 8A1D[57700000]      <1> 	mov	bl, [u.uno]
  2688                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2689 00003E26 C683[856D0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2690                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2691                              <1> 	; 05/02/2014
  2692 00003E2D 3C01                <1> 	cmp	al, 1 ; SRUN
  2693 00003E2F 740F                <1> 	je	short sysexit_6
  2694                              <1> 	;cmp	al, 2
  2695                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2696                              <1> 			  ; / this child to die
  2697                              <1> 	;jne	short sysexit_6	
  2698                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2699                              <1> 	; 05/02/2014
  2700                              <1> 	; p.stat = 2 --> waiting
  2701                              <1> 	; p.stat = 4 --> sleeping
  2702 00003E31 C686[856D0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2703                              <1> 	;dec	byte [esi+p.stat-1]
  2704                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2705 00003E38 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2706                              <1> 	; 
  2707                              <1> 	;mov	ebx, runq + 4
  2708                              <1> 		; mov $runq+4,r2 / on the runq
  2709 00003E3B E8E8110000          <1> 	call	putlu
  2710                              <1> 		; jsr r0, putlu
  2711                              <1> sysexit_6: ; 2:
  2712                              <1> 	; 31/08/2015
  2713                              <1> 		; / the process dies
  2714 00003E40 C605[57700000]00    <1> 	mov	byte [u.uno], 0
  2715                              <1> 		; clrb u.uno / put zero as the process number, 
  2716                              <1> 	           ; / so "swap" will
  2717 00003E47 E80F110000          <1> 	call	swap
  2718                              <1> 		; jsr r0,swap / overwrite process with another process
  2719                              <1> hlt_sys:
  2720                              <1> 	;sti ; 18/01/2014
  2721                              <1> hlts0:
  2722 00003E4C F4                  <1> 	hlt
  2723 00003E4D EBFD                <1> 	jmp	short hlts0
  2724                              <1> 		; 0 / and thereby kill it; halt?
  2725                              <1> 
  2726                              <1> 
  2727                              <1> syswait: ; < wait for a processs to die >
  2728                              <1> 	; 17/09/2015
  2729                              <1> 	; 02/09/2015
  2730                              <1> 	; 01/09/2015
  2731                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2732                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2733                              <1> 	;
  2734                              <1> 	; 'syswait' waits for a process die. 
  2735                              <1> 	; It works in following way:
  2736                              <1> 	;    1) From the parent process number, the parent's 
  2737                              <1> 	; 	process name is found. The p.ppid table of parent
  2738                              <1> 	;	names is then searched for this process name.
  2739                              <1> 	;	If a match occurs, r2 contains child's process
  2740                              <1> 	;	number. The child status is checked to see if it is
  2741                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2742                              <1> 	;	If it is, the child process is freed and it's name
  2743                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2744                              <1> 	;	If the child is not a zombie, nothing happens and
  2745                              <1> 	;	the search goes on through the p.ppid table until
  2746                              <1> 	;	all processes are checked or a zombie is found.
  2747                              <1> 	;    2) If no zombies are found, a check is made to see if
  2748                              <1> 	;	there are any children at all. If there are none,
  2749                              <1> 	;	an error return is made. If there are, the parent's
  2750                              <1> 	;	status is set to 2 (waiting for child to die),
  2751                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2752                              <1> 	;	is made to wait on the next process.
  2753                              <1> 	;
  2754                              <1> 	; Calling sequence:
  2755                              <1> 	;	?
  2756                              <1> 	; Arguments:
  2757                              <1> 	;	-
  2758                              <1> 	; Inputs: - 
  2759                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2760                              <1> 	; ...............................................................
  2761                              <1> 	;				
  2762                              <1> 	
  2763                              <1> ; / wait for a process to die
  2764                              <1> 
  2765                              <1> syswait_0:
  2766 00003E4F 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2767                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2768 00003E56 D0E3                <1> 	shl	bl, 1
  2769                              <1> 	;shl	bx, 1
  2770                              <1> 		; asl r1 / x2 to get index into p.pid table
  2771 00003E58 668B83[F46C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2772                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2773 00003E5F 31F6                <1> 	xor	esi, esi
  2774                              <1> 		; clr r2
  2775 00003E61 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2776                              <1> 	;xor 	cl, cl
  2777                              <1> 		; clr r3 / initialize reg 3
  2778                              <1> syswait_1: ; 1:
  2779 00003E63 6683C602            <1> 	add	si, 2
  2780                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2781                              <1> 			  ; / search table of parent processes 
  2782                              <1> 			  ; / for this process name
  2783 00003E67 663B86[146D0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2784                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2785                              <1> 			            ; / process number
  2786 00003E6E 7535                <1> 	jne	short syswait_3
  2787                              <1> 		;bne 3f / branch if no match of parent process name
  2788                              <1> 	;inc	cx
  2789 00003E70 FEC1                <1> 	inc	cl
  2790                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2791 00003E72 66D1EE              <1> 	shr	si, 1
  2792                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2793                              <1> 	; The possible states ('p.stat' values) of a process are:
  2794                              <1> 	;	0 = free or unused
  2795                              <1> 	;	1 = active
  2796                              <1> 	;	2 = waiting for a child process to die
  2797                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2798 00003E75 80BE[856D0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2799                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2800 00003E7C 7524                <1> 	jne	short syswait_2
  2801                              <1> 		; bne 2f / no, skip it
  2802 00003E7E 88BE[856D0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2803                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2804 00003E84 66D1E6              <1> 	shl	si, 1
  2805                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2806 00003E87 0FB786[F46C0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2807 00003E8E A3[08700000]        <1> 	mov	[u.r0], eax
  2808                              <1> 		; mov p.pid-2(r2),*u.r0 
  2809                              <1> 			      ; / put childs process name in (u.r0)
  2810                              <1> 	;
  2811                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2812                              <1> 	;
  2813                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2814                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2815                              <1> 	; system call loop from the application/program if it calls
  2816                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2817                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2818                              <1> 	;
  2819                              <1> 	; Note: syswait will return with error if there is not a
  2820                              <1> 	;       zombie or running process to wait.	
  2821                              <1> 	;
  2822 00003E93 6629C0              <1> 	sub	ax, ax
  2823 00003E96 668986[146D0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2824 00003E9D E905FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2825                              <1> 	;
  2826                              <1> 	;jmp	sysret
  2827                              <1> 		; br sysret1 / return cause child is dead
  2828                              <1> syswait_2: ; 2:
  2829 00003EA2 66D1E6              <1> 	shl	si, 1
  2830                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2831                              <1> syswait_3: ; 3:
  2832 00003EA5 6683FE20            <1> 	cmp	si, nproc+nproc
  2833                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2834 00003EA9 72B8                <1> 	jb	short syswait_1
  2835                              <1> 		; blt 1b / no, continue search
  2836                              <1> 	;and	cx, cx
  2837 00003EAB 20C9                <1> 	and	cl, cl
  2838                              <1> 		; tst r3 / one gets here if there are no children 
  2839                              <1> 		       ; / or children that are still active
  2840                              <1> 	; 30/10/2013
  2841 00003EAD 750B                <1> 	jnz	short syswait_4
  2842                              <1> 	;jz	error
  2843                              <1> 		; beq error1 / there are no children, error
  2844 00003EAF 890D[08700000]      <1> 	mov	[u.r0], ecx ; 0
  2845 00003EB5 E9CBFDFFFF          <1> 	jmp	error
  2846                              <1> syswait_4:
  2847 00003EBA 8A1D[57700000]      <1> 	mov	bl, [u.uno]
  2848                              <1> 		; movb u.uno,r1 / there are children so put 
  2849                              <1> 			      ; / parent process number in r1
  2850 00003EC0 FE83[856D0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2851                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2852                              <1> 				  ; / other children to die
  2853                              <1> 	; 04/11/2013
  2854 00003EC6 E890100000          <1> 	call	swap
  2855                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2856 00003ECB EB82                <1> 	jmp	syswait_0
  2857                              <1> 		; br syswait / wait on next process
  2858                              <1> 
  2859                              <1> sysfork: ; < create a new process >
  2860                              <1> 	; 18/09/2015
  2861                              <1> 	; 04/09/2015
  2862                              <1> 	; 02/09/2015
  2863                              <1> 	; 01/09/2015
  2864                              <1> 	; 28/08/2015
  2865                              <1> 	; 14/05/2015
  2866                              <1> 	; 10/05/2015
  2867                              <1> 	; 09/05/2015
  2868                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2869                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2870                              <1> 	;
  2871                              <1> 	; 'sysfork' creates a new process. This process is referred
  2872                              <1> 	; to as the child process. This new process core image is
  2873                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2874                              <1> 	; distinction is the return location and the fact that (u.r0)
  2875                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2876                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2877                              <1> 	; 'sysfork' works in the following manner: 	
  2878                              <1> 	;    1) The process status table (p.stat) is searched to find
  2879                              <1> 	;	a process number that is unused. If none are found
  2880                              <1> 	;	an error occurs.
  2881                              <1> 	;    2) when one is found, it becomes the child process number
  2882                              <1> 	;	and it's status (p.stat) is set to active.
  2883                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2884                              <1> 	;	character in that tty buffer is cleared.
  2885                              <1> 	;    4) The child process is put on the lowest priority run 
  2886                              <1> 	;	queue via 'putlu'.
  2887                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2888                              <1> 	;	it is a unique number) and is put in the child's unique
  2889                              <1> 	;	identifier; process id (p.pid).
  2890                              <1> 	;    6) The process name of the parent is then obtained and
  2891                              <1> 	;	placed in the unique identifier of the parent process
  2892                              <1> 	;	name is then put in 'u.r0'.	
  2893                              <1> 	;    7) The child process is then written out on disk by
  2894                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2895                              <1> 	;	and the child is born. (The child process is written 
  2896                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2897                              <1> 	;	number.)
  2898                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2899                              <1> 	;    9) The child process name is put in 'u.r0'.
  2900                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2901                              <1> 	;	create the return address for the parent process.
  2902                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2903                              <1> 	;	the parent has opened. For each file the parent has
  2904                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2905                              <1> 	;	to indicate that the child process also has opened
  2906                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2907                              <1> 	;
  2908                              <1> 	; Calling sequence:
  2909                              <1> 	;	from shell ?
  2910                              <1> 	; Arguments:
  2911                              <1> 	;	-
  2912                              <1> 	; Inputs: -
  2913                              <1> 	; Outputs: *u.r0 - child process name
  2914                              <1> 	; ...............................................................
  2915                              <1> 	;	
  2916                              <1> 	; Retro UNIX 8086 v1 modification: 
  2917                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2918                              <1> 	;	= process id of child a parent process returns
  2919                              <1> 	;	= process id of parent when a child process returns
  2920                              <1> 	;
  2921                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  2922                              <1> 	;	in following manner: (with an example: c library, fork)
  2923                              <1> 	;	
  2924                              <1> 	;	1:
  2925                              <1> 	;		sys	fork
  2926                              <1> 	;			br 1f  / child process returns here
  2927                              <1> 	;		bes	2f     / parent process returns here
  2928                              <1> 	;		/ pid of new process in r0
  2929                              <1> 	;		rts	pc
  2930                              <1> 	;	2: / parent process condionally branches here
  2931                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  2932                              <1> 	;		rts	pc
  2933                              <1> 	;
  2934                              <1> 	;	1: / child process brances here
  2935                              <1> 	;		clr	r0   / pid = 0 in child process
  2936                              <1> 	;		rts	pc
  2937                              <1> 	;
  2938                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  2939                              <1> 	;		// pid = fork();
  2940                              <1> 	;		//
  2941                              <1> 	;		// pid == 0 in child process; 
  2942                              <1> 	;		// pid == -1 means error return
  2943                              <1> 	;		// in child, 
  2944                              <1> 	;		//	parents id is in par_uid if needed
  2945                              <1> 	;		
  2946                              <1> 	;		_fork:
  2947                              <1> 	;			mov	$.fork,eax
  2948                              <1> 	;			int	$0x30
  2949                              <1> 	;			jmp	1f
  2950                              <1> 	;			jnc	2f
  2951                              <1> 	;			jmp	cerror
  2952                              <1> 	;		1:
  2953                              <1> 	;			mov	eax,_par_uid
  2954                              <1> 	;			xor	eax,eax
  2955                              <1> 	;		2:
  2956                              <1> 	;			ret
  2957                              <1> 	;
  2958                              <1> 	;	In Retro UNIX 8086 v1,
  2959                              <1> 	;	'sysfork' returns in following manner:
  2960                              <1> 	;	
  2961                              <1> 	;		mov	ax, sys_fork
  2962                              <1> 	;		mov	bx, offset @f ; routine for child
  2963                              <1> 	;		int	20h
  2964                              <1> 	;		jc	error
  2965                              <1> 	;		
  2966                              <1> 	;	; Routine for parent process here (just after 'jc')
  2967                              <1> 	;		mov	word ptr [pid_of_child], ax
  2968                              <1> 	;		jmp	next_routine_for_parent	
  2969                              <1> 	;
  2970                              <1> 	;	@@: ; routine for child process here				
  2971                              <1> 	;		....	
  2972                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  2973                              <1> 	;	       for child process by using BX input.
  2974                              <1> 	;	      (at first, parent process will return then 
  2975                              <1> 	;	      child process will return -after swapped in-
  2976                              <1> 	;	      'syswait' is needed in parent process
  2977                              <1> 	;	      if return from child process will be waited for.)
  2978                              <1> 	;	  				
  2979                              <1> 	
  2980                              <1> ; / create a new process
  2981                              <1> 	; EBX = return address for child process 
  2982                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  2983 00003ECD 31F6                <1> 	xor 	esi, esi
  2984                              <1> 		; clr r1
  2985                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  2986 00003ECF 46                  <1> 	inc	esi
  2987                              <1> 		; inc r1
  2988 00003ED0 80BE[856D0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  2989                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  2990 00003ED7 760B                <1> 	jna	short sysfork_2	
  2991                              <1> 		; beq 1f / it's unused so branch
  2992 00003ED9 6683FE10            <1> 	cmp	si, nproc
  2993                              <1> 		; cmp r1,$nproc / all processes checked
  2994 00003EDD 72F0                <1> 	jb	short sysfork_1
  2995                              <1> 		; blt 1b / no, branch back
  2996                              <1> 	;
  2997                              <1> 	; Retro UNIX 8086 v1. modification:
  2998                              <1> 	;	Parent process returns from 'sysfork' to address 
  2999                              <1> 	;	which is just after 'sysfork' system call in parent
  3000                              <1> 	;	process. Child process returns to address which is put
  3001                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3002                              <1> 	;
  3003                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3004                              <1> 		             ; / to old process return
  3005                              <1> 		; br error1 / no room for a new process
  3006 00003EDF E9A1FDFFFF          <1> 	jmp	error
  3007                              <1> sysfork_2: ; 1:
  3008 00003EE4 E851F0FFFF          <1> 	call	allocate_page
  3009 00003EE9 0F8296FDFFFF        <1> 	jc	error
  3010 00003EEF 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3011                              <1> 	; Retro UNIX 386 v1 modification!
  3012 00003EF0 E83EF2FFFF          <1> 	call	duplicate_page_dir
  3013                              <1> 		; EAX = New page directory 
  3014 00003EF5 730B                <1> 	jnc	short sysfork_3
  3015 00003EF7 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3016 00003EF8 E805F2FFFF          <1> 	call 	deallocate_page
  3017 00003EFD E983FDFFFF          <1> 	jmp	error
  3018                              <1> sysfork_3:
  3019                              <1> 	; Retro UNIX 386 v1 modification !
  3020 00003F02 56                  <1> 	push	esi
  3021 00003F03 E8CA100000          <1> 	call	wswap ; save current user (u) structure, user registers
  3022                              <1> 		      ; and interrupt return components (for IRET)
  3023 00003F08 8705[61700000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3024 00003F0E A3[65700000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3025 00003F13 5E                  <1> 	pop	esi
  3026 00003F14 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3027                              <1> 		; [u.usp] = esp
  3028 00003F15 89F7                <1> 	mov	edi, esi
  3029 00003F17 66C1E702            <1> 	shl	di, 2
  3030 00003F1B 8987[926D0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3031 00003F21 A3[58700000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3032                              <1> 	; 28/08/2015
  3033 00003F26 0FB605[57700000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3034                              <1> 		; movb u.uno,-(sp) / save parent process number
  3035 00003F2D 89C7                <1> 	mov	edi, eax
  3036 00003F2F 50                  <1>         push	eax ; ** 
  3037 00003F30 8A87[556D0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3038                              <1> 	; 18/09/2015
  3039                              <1> 	;mov     [esi+p.ttyc-1], al ; set child's console tty
  3040                              <1> 	;mov     [esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3041 00003F36 668986[556D0000]    <1> 	mov     [esi+p.ttyc-1], ax ; al - set child's console tty
  3042                              <1> 				   ; ah - reset child's wait channel	
  3043 00003F3D 89F0                <1> 	mov	eax, esi
  3044 00003F3F A2[57700000]        <1> 	mov	[u.uno], al ; child process number
  3045                              <1> 		;movb r1,u.uno / set child process number to r1
  3046 00003F44 FE86[856D0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3047                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3048                              <1> 				; / process to active status
  3049                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3050                              <1> 			      ; / control tty buffer in r2
  3051                              <1>                 ; beq 2f / branch, if no such tty assigned
  3052                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3053                              <1> 	; 2:
  3054 00003F4A 53                  <1> 	push	ebx  ; * return address for the child process
  3055                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3056                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3057                              <1> 		; mov $runq+4,r2
  3058 00003F4B E8D8100000          <1> 	call	putlu 
  3059                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3060                              <1> 			   ; / run queue
  3061 00003F50 66D1E6              <1> 	shl	si, 1
  3062                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3063                              <1> 		       ; / into p.pid table
  3064 00003F53 66FF05[F66F0000]    <1> 	inc	word [mpid]
  3065                              <1> 		; inc mpid / increment m.pid; get a new process name
  3066 00003F5A 66A1[F66F0000]      <1> 	mov	ax, [mpid]
  3067 00003F60 668986[F46C0000]    <1> 	mov	[esi+p.pid-2], ax
  3068                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3069                              <1> 				    ; / in child process' name slot
  3070 00003F67 5A                  <1> 	pop	edx  ; * return address for the child process
  3071                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3072 00003F68 5B                  <1>   	pop	ebx  ; **
  3073                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3074                              <1> 		; movb (sp),r2 / put parent process number in r2
  3075 00003F69 66D1E3              <1> 	shl 	bx, 1
  3076                              <1> 		;asl r2 / multiply by 2 to get index into below tables
  3077                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3078 00003F6C 668B83[F46C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3079                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3080                              <1> 				   ; / process
  3081 00003F73 668986[146D0000]    <1> 	mov	[esi+p.ppid-2], ax
  3082                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3083                              <1> 			  ; / in parent process slot for child
  3084 00003F7A A3[08700000]        <1> 	mov	[u.r0], eax	
  3085                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3086                              <1> 			     ; / at location where r0 was saved
  3087 00003F7F 8B2D[00700000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3088 00003F85 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3089                              <1> 			   ; * return address for the child process
  3090                              <1> 		; mov $sysret1,-(sp) /
  3091                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3092                              <1> 			      ; / user is swapped out
  3093                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3094                              <1> 	; 04/09/2015 - 01/09/2015
  3095                              <1> 	; [u.usp] = esp
  3096 00003F88 68[A53C0000]        <1> 	push	sysret ; ***
  3097 00003F8D 8925[04700000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3098                              <1> 			     ; (for child process)	
  3099 00003F93 31C0                <1> 	xor 	eax, eax
  3100 00003F95 66A3[38700000]      <1> 	mov 	[u.ttyp], ax ; 0
  3101                              <1> 	;
  3102 00003F9B E832100000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3103                              <1> 		;jsr r0,wswap / put child process out on drum
  3104                              <1> 		;jsr r0,unpack / unpack user stack
  3105                              <1> 		;mov u.usp,sp / restore user stack pointer
  3106                              <1> 		; tst (sp)+ / bump stack pointer
  3107                              <1> 	; Retro UNIX 386 v1 modification !
  3108 00003FA0 58                  <1> 	pop	eax ; ***
  3109 00003FA1 66D1E3              <1> 	shl	bx, 1
  3110 00003FA4 8B83[926D0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3111 00003FAA E84C100000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3112                              <1> 		      ; registers and return address (for IRET)
  3113                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3114 00003FAF 0FB705[F66F0000]    <1>         movzx   eax, word [mpid]
  3115 00003FB6 A3[08700000]        <1> 	mov	[u.r0], eax
  3116                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3117                              <1> 			       ; / where r0 was saved
  3118                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3119                              <1> 			          ; / process return
  3120                              <1> 	;xor	ebx, ebx
  3121 00003FBB 31F6                <1> 	xor     esi, esi
  3122                              <1> 		;clr r1
  3123                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3124                              <1> 	      ; / opened by the parent process
  3125                              <1> 	; 01/09/2015
  3126                              <1> 	;xor	bh, bh
  3127                              <1> 	;mov 	bl, [esi+u.fp]
  3128 00003FBD 8A86[0E700000]      <1> 	mov 	al, [esi+u.fp]
  3129                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3130                              <1>         ;or      bl, bl
  3131 00003FC3 08C0                <1> 	or	al, al
  3132 00003FC5 740D                <1> 	jz	short sysfork_5	
  3133                              <1> 		; beq 2f / file has not been opened by parent, 
  3134                              <1> 		       ; / so branch
  3135 00003FC7 B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3136 00003FC9 F6E4                <1> 	mul	ah
  3137                              <1> 	;movzx	ebx, ax
  3138 00003FCB 6689C3              <1> 	mov	bx, ax
  3139                              <1> 	;shl     bx, 3
  3140                              <1> 		; asl r2 / multiply by 8
  3141                              <1>        		; asl r2 / to get index into fsp table
  3142                              <1>        		; asl r2
  3143 00003FCE FE83[D46D0000]      <1>   	inc     byte [ebx+fsp-2]
  3144                              <1> 		; incb fsp-2(r2) / increment number of processes
  3145                              <1> 			     ; / using file, because child will now be
  3146                              <1> 			     ; / using this file
  3147                              <1> sysfork_5: ; 2:
  3148 00003FD4 46                  <1>         inc     esi
  3149                              <1> 		; inc r1 / get next open file
  3150 00003FD5 6683FE0A            <1>         cmp     si, 10
  3151                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3152                              <1> 			  ; / can be opened
  3153 00003FD9 72E2                <1> 	jb	short sysfork_4	
  3154                              <1> 		; blt 1b / check next entry
  3155 00003FDB E9C5FCFFFF          <1> 	jmp	sysret
  3156                              <1> 		; br sysret1
  3157                              <1> 
  3158                              <1> sysread: ; < read from file >
  3159                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3160                              <1> 	; 13/05/2015
  3161                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3162                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3163                              <1> 	;
  3164                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3165                              <1> 	; characters to be read. If finds the file from the file
  3166                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3167                              <1> 	; is returned from a successful open call (sysopen).
  3168                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3169                              <1> 	; is read into core via 'readi'.
  3170                              <1> 	;
  3171                              <1> 	; Calling sequence:
  3172                              <1> 	;	sysread; buffer; nchars
  3173                              <1> 	; Arguments:
  3174                              <1> 	;	buffer - location of contiguous bytes where 
  3175                              <1> 	;		 input will be placed.
  3176                              <1> 	;	nchars - number of bytes or characters to be read.
  3177                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3178                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3179                              <1> 	; ...............................................................
  3180                              <1> 	;				
  3181                              <1> 	; Retro UNIX 8086 v1 modification: 
  3182                              <1> 	;       'sysread' system call has three arguments; so,
  3183                              <1> 	;	* 1st argument, file descriptor is in BX register
  3184                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3185                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3186                              <1> 	;
  3187                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3188                              <1> 	;	to the user with number of bytes read. 
  3189                              <1> 	;
  3190 00003FE0 E840000000          <1> 	call	rw1
  3191                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3192                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3193                              <1>        	; 24/12/2021
  3194 00003FE5 7239                <1> 	jc	short sysread_err
  3195 00003FE7 F6C480              <1> 	test	ah, 80h
  3196                              <1> 		; tst r1 / negative i-number?
  3197 00003FEA 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3198                              <1> 	;jnz	error
  3199                              <1> 		; ble error1 / yes, error 1 to read
  3200                              <1> 			   ; / it should be positive
  3201 00003FEC E8B2140000          <1> 	call	readi
  3202                              <1> 		; jsr r0,readi / read data into core
  3203 00003FF1 EB14                <1> 	jmp	short rw0
  3204                              <1> 		; br 1f
  3205                              <1> syswrite: ; < write to file >
  3206                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3207                              <1> 	; 13/05/2015
  3208                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3209                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3210                              <1> 	;
  3211                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3212                              <1> 	; and the number of characters to write. If finds the file
  3213                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3214                              <1> 	; descriptor is returned from a successful open or create call
  3215                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3216                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3217                              <1> 	;
  3218                              <1> 	; Calling sequence:
  3219                              <1> 	;	syswrite; buffer; nchars
  3220                              <1> 	; Arguments:
  3221                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3222                              <1> 	;	nchars - number of characters to be written.
  3223                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3224                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3225                              <1> 	; ...............................................................
  3226                              <1> 	;				
  3227                              <1> 	; Retro UNIX 8086 v1 modification: 
  3228                              <1> 	;       'syswrite' system call has three arguments; so,
  3229                              <1> 	;	* 1st argument, file descriptor is in BX register
  3230                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3231                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3232                              <1> 	;
  3233                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3234                              <1> 	;	to the user with number of bytes written. 
  3235                              <1> 	;
  3236 00003FF3 E82D000000          <1> 	call	rw1
  3237                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3238                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3239                              <1>        	; 24/12/2021
  3240 00003FF8 7226                <1> 	jc	short syswrite_err
  3241 00003FFA F6C480              <1>         test	ah, 80h
  3242                              <1> 		; tst r1 / positive i-number ?
  3243 00003FFD 7417                <1>         jz	short rw3 ; 13/05/2015
  3244                              <1> 	;jz	error
  3245                              <1> 		; bge error1 / yes, error 1 
  3246                              <1> 			   ; / negative i-number means write
  3247 00003FFF 66F7D8              <1>         neg	ax
  3248                              <1> 		; neg r1 / make it positive
  3249 00004002 E88C160000          <1> 	call	writei
  3250                              <1>         	; jsr r0,writei / write data
  3251                              <1> rw0: ; 1:
  3252 00004007 A1[30700000]        <1>         mov	eax, [u.nread]
  3253 0000400C A3[08700000]        <1> 	mov	[u.r0], eax
  3254                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3255                              <1> 				  ; / into (u.r0)
  3256 00004011 E98FFCFFFF          <1> 	jmp	sysret
  3257                              <1>         	; br sysret1
  3258                              <1> 
  3259                              <1> rw3: 
  3260                              <1> 	; 13/05/2015
  3261 00004016 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3261 0000401E 0000                <1>
  3262                              <1> 	;stc
  3263                              <1> 	;retn
  3264                              <1> 	; 24/12/2021 (BugFix)
  3265                              <1> sysread_err:
  3266                              <1> syswrite_err:
  3267 00004020 E960FCFFFF          <1> 	jmp	error
  3268                              <1> 
  3269                              <1> rw1:	
  3270                              <1> 	; 14/05/2015
  3271                              <1> 	; 13/05/2015
  3272                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3273                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3274                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3275                              <1> 	;
  3276                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3277                              <1> 				;(in the user's virtual memory space)
  3278                              <1> 	;mov	[u.count], edx 
  3279                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3280                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3281                              <1> 	;;mov	eax, ebx ; file descriptor
  3282                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3283                              <1> 		             ; / (index to u.fp table) in r1
  3284                              <1> 	; 13/05/2015
  3285 00004025 C705[08700000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3285 0000402D 0000                <1>
  3286                              <1> 	;
  3287                              <1> 	;; call	getf
  3288                              <1>         ; eBX = File descriptor
  3289 0000402F E88C0A0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3290                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3291                              <1> 	; AX = I-number of the file ; negative i-number means write
  3292                              <1> 	; 13/05/2015
  3293 00004034 6683F801            <1> 	cmp 	ax, 1
  3294 00004038 7217                <1> 	jb	short rw2
  3295                              <1> 	;
  3296 0000403A 890D[28700000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3297                              <1> 				;(in the user's virtual memory space)
  3298 00004040 8915[2C700000]      <1> 	mov	[u.count], edx 
  3299                              <1> 	; 14/05/2015
  3300 00004046 C705[5D700000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3300 0000404E 0000                <1>
  3301 00004050 C3                  <1> 	retn
  3302                              <1>         	; rts r0
  3303                              <1> rw2:
  3304                              <1> 	; 13/05/2015
  3305 00004051 C705[5D700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3305 00004059 0000                <1>
  3306 0000405B C3                  <1> 	retn
  3307                              <1> 
  3308                              <1> sysopen: ;<open file>
  3309                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3310                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3311                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3312                              <1> 	;
  3313                              <1> 	; 'sysopen' opens a file in following manner:
  3314                              <1> 	;    1) The second argument in a sysopen says whether to
  3315                              <1> 	;	open the file ro read (0) or write (>0).
  3316                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3317                              <1> 	;    3) The file is opened by 'iopen'.
  3318                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3319                              <1> 	;	and the user's open file list - u.fp.
  3320                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3321                              <1> 	;	b) An entry for the file is created in the fsp table.
  3322                              <1> 	;	c) The number of this entry is put on u.fp list.
  3323                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3324                              <1> 	;	   to by u.r0.
  3325                              <1> 	;
  3326                              <1> 	; Calling sequence:
  3327                              <1> 	;	sysopen; name; mode
  3328                              <1> 	; Arguments:
  3329                              <1> 	;	name - file name or path name
  3330                              <1> 	;	mode - 0 to open for reading
  3331                              <1> 	;	       1 to open for writing
  3332                              <1> 	; Inputs: (arguments)
  3333                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3334                              <1> 	;		  is put into r0's location on the stack.	
  3335                              <1> 	; ...............................................................
  3336                              <1> 	;				
  3337                              <1> 	; Retro UNIX 8086 v1 modification: 
  3338                              <1> 	;       'sysopen' system call has two arguments; so,
  3339                              <1> 	;	* 1st argument, name is pointed to by BX register
  3340                              <1> 	;	* 2nd argument, mode is in CX register
  3341                              <1> 	;
  3342                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3343                              <1> 	;	to the user with the file descriptor/number 
  3344                              <1> 	;	(index to u.fp list).
  3345                              <1> 	;
  3346                              <1> 	;call	arg2
  3347                              <1> 	; * name - 'u.namep' points to address of file/path name
  3348                              <1> 	;          in the user's program segment ('u.segmnt')
  3349                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3350                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3351                              <1> 	;          which is on top of stack.
  3352                              <1> 	;
  3353                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3354                              <1> 	;
  3355                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3356                              <1> 
  3357 0000405C 891D[20700000]      <1> 	mov	[u.namep], ebx
  3358                              <1> 	; 24/12/2021 (cx -> ecx)
  3359 00004062 51                  <1> 	push	ecx ; * 
  3360 00004063 E88F0A0000          <1> 	call	namei
  3361                              <1> 		; jsr r0,namei / i-number of file in r1
  3362                              <1>      	;and	ax, ax
  3363                              <1> 	;jz	error ; File not found
  3364 00004068 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3365                              <1> 	;jc	error ; 27/05/2013
  3366                              <1> 		; br  error2 / file not found
  3367                              <1>    	; 24/12/2021
  3368                              <1> 	;pop	edx ; * ; mode
  3369                              <1> 	;push	edx ; *
  3370 0000406A 8B1424              <1> 	mov	edx, [esp] ; *
  3371                              <1> 	; edx = open mode (0 or 1)
  3372                              <1> 	;or	dx, dx
  3373 0000406D 08D2                <1> 	or	dl, dl
  3374                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3375                              <1> 		         ; / 0 means, open for read)
  3376 0000406F 7403                <1> 	jz	short sysopen_0
  3377                              <1> 		; beq 1f / yes, leave i-number positive
  3378                              <1> syscreat_0: ; 27/12/2015
  3379 00004071 66F7D8              <1> 	neg	ax
  3380                              <1>         	; neg r1 / open for writing so make i-number negative
  3381                              <1> sysopen_0: ;1:
  3382 00004074 E8BE190000          <1> 	call	iopen
  3383                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3384 00004079 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3385                              <1> 	;and	dx, dx
  3386 0000407A 20D2                <1> 	and	dl, dl
  3387                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3388 0000407C 7403                <1> 	jz	short sysopen_2
  3389                              <1>         	; beq op1 / is open for read op1
  3390                              <1> sysopen_1: ;op0:
  3391 0000407E 66F7D8              <1> 	neg	ax
  3392                              <1>         	; neg r1 
  3393                              <1> 	;; NOTE: iopen always make i-number positive.
  3394                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3395                              <1> sysopen_2: ;op1:
  3396 00004081 31F6                <1>         xor     esi, esi
  3397                              <1>         	; clr r2 / clear registers
  3398 00004083 31DB                <1>         xor     ebx, ebx
  3399                              <1> 		; clr r3
  3400                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3401 00004085 389E[0E700000]      <1>         cmp     [esi+u.fp], bl ; 0
  3402                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3403 0000408B 7625                <1>         jna      short sysopen_4
  3404                              <1> 		; beq 1f / if byte in list is 0 branch
  3405 0000408D 46                  <1>         inc     esi
  3406                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3407 0000408E 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3408                              <1> 		; cmp r2,$10. / reached end of list?
  3409 00004092 72F1                <1> 	jb	short sysopen_3
  3410                              <1> 		; blt 1b / no, go back
  3411                              <1> toomanyf:
  3412                              <1> 	; 14/05/2015
  3413 00004094 C705[5D700000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3413 0000409C 0000                <1>
  3414 0000409E E9E2FBFFFF          <1> 	jmp	error
  3415                              <1>         	; br error2 / yes, error (no files open)
  3416                              <1> fnotfound: 
  3417                              <1> 	; 14/05/2015
  3418 000040A3 C705[5D700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3418 000040AB 0000                <1>
  3419 000040AD E9D3FBFFFF          <1> 	jmp	error
  3420                              <1> 
  3421                              <1> sysopen_4: ; 1:
  3422 000040B2 6683BB[D66D0000]00  <1>         cmp     word [ebx+fsp], 0
  3423                              <1> 		; tst fsp(r3) / scan fsp entries
  3424 000040BA 760D                <1>         jna     short sysopen_5
  3425                              <1> 		; beq 1f / if 0 branch
  3426                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3427 000040BC 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3428                              <1> 		; add $8.,r3 / add 8 to r3 
  3429                              <1> 			; / to bump it to next entry mfsp table
  3430 000040C0 6681FBF401          <1>         cmp     bx, nfiles*10
  3431                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3432 000040C5 72EB                <1> 	jb	short sysopen_4
  3433                              <1>        		; blt 1b / no, back
  3434                              <1> 	;jmp	error
  3435                              <1>         ;	; br error2 / yes, error
  3436                              <1> 	; 24/12/2021
  3437 000040C7 EBCB                <1> 	jmp	short toomanyf
  3438                              <1> 
  3439                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3440 000040C9 668983[D66D0000]    <1>         mov     [ebx+fsp], ax
  3441                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3442                              <1> 			; / into next available entry in fsp table,
  3443 000040D0 668B3D[EE6F0000]    <1> 	mov	di, [cdev] ; word ? byte ?
  3444 000040D7 6689BB[D86D0000]    <1>         mov     [ebx+fsp+2], di ; device number
  3445                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3446 000040DE 31FF                <1>         xor	edi, edi
  3447 000040E0 89BB[DA6D0000]      <1>         mov     [ebx+fsp+4], edi ; offset pointer (0)
  3448                              <1> 		; clr fsp+4(r3)
  3449 000040E6 6689BB[DE6D0000]    <1>         mov     [ebx+fsp+8], di ; open count (0), deleted flag (0)
  3450                              <1>        		; clr fsp+6(r3) / clear the next two words
  3451 000040ED 89D8                <1>   	mov	eax, ebx
  3452 000040EF B30A                <1> 	mov	bl, 10
  3453 000040F1 F6F3                <1> 	div	bl 
  3454                              <1> 		; asr r3
  3455                              <1> 		; asr r3 / divide by 8 
  3456                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3457 000040F3 FEC0                <1> 	inc	al
  3458                              <1>         	; inc r3 / add 1 to get fsp entry number
  3459 000040F5 8886[0E700000]      <1>         mov     [esi+u.fp], al
  3460                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3461                              <1> 			; / next available slot in u.fp list
  3462 000040FB 8935[08700000]      <1>         mov     [u.r0], esi
  3463                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3464                              <1> 			     ; / into r0 loc on stack
  3465 00004101 E99FFBFFFF          <1>         jmp	sysret
  3466                              <1> 		; br sysret2
  3467                              <1> 
  3468                              <1> 	;
  3469                              <1> 	; 'fsp' table (10 bytes/entry)
  3470                              <1> 	; bit 15				   bit 0
  3471                              <1> 	; ---|-------------------------------------------
  3472                              <1> 	; r/w|		i-number of open file
  3473                              <1> 	; ---|-------------------------------------------
  3474                              <1> 	;		   device number
  3475                              <1> 	; -----------------------------------------------
  3476                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3477                              <1> 	; -----------------------------------------------
  3478                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3479                              <1> 	; ----------------------|------------------------
  3480                              <1> 	;  flag that says file 	| number of processes
  3481                              <1> 	;   has been deleted	| that have file open 
  3482                              <1> 	; ----------------------|------------------------
  3483                              <1> 	;
  3484                              <1> 
  3485                              <1> syscreat: ; < create file >
  3486                              <1> 	; 24/12/2021
  3487                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3488                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3489                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3490                              <1> 	;
  3491                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3492                              <1> 	; u.namep points to name of the file and mode is put
  3493                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3494                              <1> 	; If the file aready exists, it's mode and owner remain 
  3495                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3496                              <1> 	; did not exist, an i-node is created with the new mode via
  3497                              <1> 	; 'maknod' whether or not the file already existed, it is
  3498                              <1> 	; open for writing. The fsp table is then searched for a free
  3499                              <1> 	; entry. When a free entry is found, proper data is placed
  3500                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3501                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3502                              <1> 	; is put in the user's r0. 			
  3503                              <1> 	;
  3504                              <1> 	; Calling sequence:
  3505                              <1> 	;	syscreate; name; mode
  3506                              <1> 	; Arguments:
  3507                              <1> 	;	name - name of the file to be created
  3508                              <1> 	;	mode - mode of the file to be created
  3509                              <1> 	; Inputs: (arguments)
  3510                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3511                              <1> 	;		   (the file descriptor of new file)
  3512                              <1> 	; ...............................................................
  3513                              <1> 	;				
  3514                              <1> 	; Retro UNIX 8086 v1 modification: 
  3515                              <1> 	;       'syscreate' system call has two arguments; so,
  3516                              <1> 	;	* 1st argument, name is pointed to by BX register
  3517                              <1> 	;	* 2nd argument, mode is in CX register
  3518                              <1> 	;
  3519                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3520                              <1> 	;	to the user with the file descriptor/number 
  3521                              <1> 	;	(index to u.fp list).
  3522                              <1> 	;
  3523                              <1> 	;call	arg2
  3524                              <1> 	; * name - 'u.namep' points to address of file/path name
  3525                              <1> 	;          in the user's program segment ('u.segmnt')
  3526                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3527                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3528                              <1> 	;          which is on top of stack.
  3529                              <1> 	;
  3530                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3531                              <1> 			    ; / on stack
  3532 00004106 891D[20700000]      <1> 	mov	[u.namep], ebx ; file name address
  3533                              <1> 	;push	cx ; mode
  3534                              <1> 	; 24/12/2021
  3535 0000410C 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3536 0000410D E8E5090000          <1> 	call 	namei        	
  3537                              <1> 		; jsr r0,namei / get the i-number
  3538                              <1>         ;and	ax, ax
  3539                              <1> 	;jz	short syscreat_2	       	
  3540 00004112 721E                <1> 	jc	short syscreat_2
  3541                              <1> 		; br  2f / if file doesn't exist 2f
  3542                              <1> 	; 27/12/2015
  3543 00004114 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3544                              <1>         ;jb	syscreat_0 ; yes
  3545                              <1> 	; 24/12/2021
  3546 00004118 7305                <1> 	jnb	short syscreat_1
  3547 0000411A E952FFFFFF          <1> 	jmp	syscreat_0
  3548                              <1> syscreat_1:
  3549 0000411F 66F7D8              <1> 	neg 	ax
  3550                              <1>         	; neg r1 / if file already exists make i-number 
  3551                              <1> 		       ; / negative (open for writing)
  3552 00004122 E810190000          <1> 	call	iopen
  3553                              <1>         	; jsr r0,iopen /
  3554 00004127 E8CE120000          <1> 	call	itrunc
  3555                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3556                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3557                              <1> 	; 04/12/2021
  3558 0000412C 59                  <1> 	pop	ecx
  3559 0000412D E94CFFFFFF          <1>         jmp     sysopen_1
  3560                              <1>         	; br op0
  3561                              <1> syscreat_2: ; 2: / file doesn't exist
  3562                              <1> 	;pop	ax
  3563                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3564                              <1> 	; 24/12/2021
  3565 00004132 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3566 00004133 30E4                <1> 	xor	ah, ah	
  3567                              <1>         	; bic $!377,r1 / clear upper byte
  3568 00004135 E8880C0000          <1> 	call 	maknod
  3569                              <1>         	; jsr r0,maknod / make an i-node for this file
  3570 0000413A 66A1[3A700000]      <1> 	mov	ax, [u.dirbuf]
  3571                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3572                              <1> 			        ; / for this new file in r1
  3573 00004140 E939FFFFFF          <1>         jmp     sysopen_1
  3574                              <1>         	; br op0 / open the file
  3575                              <1> 
  3576                              <1> sysmkdir: ; < make directory >
  3577                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3578                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3579                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3580                              <1> 	;
  3581                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3582                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3583                              <1> 	; The special entries '.' and '..' are not present.
  3584                              <1> 	; Errors are indicated if the directory already exists or		
  3585                              <1> 	; user is not the super user. 
  3586                              <1> 	;
  3587                              <1> 	; Calling sequence:
  3588                              <1> 	;	sysmkdir; name; mode
  3589                              <1> 	; Arguments:
  3590                              <1> 	;	name - points to the name of the directory
  3591                              <1> 	;	mode - mode of the directory
  3592                              <1> 	; Inputs: (arguments)
  3593                              <1> 	; Outputs: -
  3594                              <1> 	;    (sets 'directory' flag to 1; 
  3595                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3596                              <1> 	; ...............................................................
  3597                              <1> 	;				
  3598                              <1> 	; Retro UNIX 8086 v1 modification: 
  3599                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3600                              <1> 	;	* 1st argument, name is pointed to by BX register
  3601                              <1> 	;	* 2nd argument, mode is in CX register
  3602                              <1> 	;
  3603                              <1> 		
  3604                              <1> ; / make a directory
  3605                              <1> 
  3606                              <1> 	;call	arg2
  3607                              <1> 	; * name - 'u.namep' points to address of file/path name
  3608                              <1> 	;          in the user's program segment ('u.segmnt')
  3609                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3610                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3611                              <1> 	;          which is on top of stack.
  3612                              <1> 
  3613                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3614                              <1> 			    ; / on stack
  3615 00004145 891D[20700000]      <1> 	mov	[u.namep], ebx
  3616                              <1> 	;push	cx ; mode
  3617                              <1> 	; 24/12/2021
  3618 0000414B 51                  <1> 	push	ecx ; cx = mode
  3619 0000414C E8A6090000          <1> 	call	namei
  3620                              <1>         	; jsr r0,namei / get the i-number
  3621                              <1>         	;     br .+4 / if file not found branch around error
  3622                              <1>         ;xor 	ax, ax
  3623                              <1> 	;jnz	error
  3624 00004151 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3625                              <1> 	;jnc	error	
  3626                              <1> 		; br  error2 / directory already exists (error)
  3627 00004153 803D[54700000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3628                              <1>         	;tstb u.uid / is user the super user
  3629 0000415A 7621                <1> 	jna	short dir_access_err ; 14/05/2015
  3630                              <1> 	;jna	error
  3631                              <1>         	;bne error2 / no, not allowed
  3632                              <1> 	;pop	ax
  3633                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3634                              <1> 	; 24/12/2021
  3635 0000415C 58                  <1> 	pop	eax  ; ax = mode
  3636 0000415D 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3637                              <1>         	;bic $!317,r1 / all but su and ex
  3638                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3639 00004161 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3640                              <1>         	;bis $40000,r1 / directory flag
  3641 00004164 E8590C0000          <1> 	call	maknod
  3642                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3643 00004169 E937FBFFFF          <1> 	jmp	sysret
  3644                              <1>         	;br sysret2 /
  3645                              <1> dir_exists:
  3646                              <1> 	; 14/05/2015
  3647 0000416E C705[5D700000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3647 00004176 0000                <1>
  3648 00004178 E908FBFFFF          <1> 	jmp	error
  3649                              <1> dir_access_err:
  3650                              <1> 	; 14/05/2015
  3651 0000417D C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3651 00004185 0000                <1>
  3652 00004187 E9F9FAFFFF          <1> 	jmp	error
  3653                              <1> 
  3654                              <1> sysclose: ;<close file>
  3655                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3656                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3657                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3658                              <1> 	;
  3659                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3660                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3661                              <1> 	; is put in r1 and 'fclose' is called.
  3662                              <1> 	;
  3663                              <1> 	; Calling sequence:
  3664                              <1> 	;	sysclose
  3665                              <1> 	; Arguments:
  3666                              <1> 	;	-  
  3667                              <1> 	; Inputs: *u.r0 - file descriptor
  3668                              <1> 	; Outputs: -
  3669                              <1> 	; ...............................................................
  3670                              <1> 	;				
  3671                              <1> 	; Retro UNIX 8086 v1 modification:
  3672                              <1> 	;	 The user/application program puts file descriptor
  3673                              <1> 	;        in BX register as 'sysclose' system call argument.
  3674                              <1> 	; 	 (argument transfer method 1)
  3675                              <1> 
  3676                              <1> 	; / close the file
  3677                              <1> 	
  3678 0000418C 89D8                <1> 	mov 	eax, ebx
  3679 0000418E E8E9080000          <1> 	call 	fclose
  3680                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3681                              <1> 		; jsr r0,fclose / close the file
  3682                              <1>                	; br error2 / unknown file descriptor
  3683                              <1> 		; br sysret2
  3684                              <1> 	; 14/05/2015
  3685                              <1> 	;jnc	sysret
  3686                              <1> 	; 04/12/2021
  3687 00004193 7205                <1> 	jc	short sysclose_1
  3688 00004195 E90BFBFFFF          <1> 	jmp	sysret
  3689                              <1> sysclose_1:
  3690 0000419A C705[5D700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3690 000041A2 0000                <1>
  3691 000041A4 E9DCFAFFFF          <1> 	jmp	error
  3692                              <1> 
  3693                              <1> sysemt:
  3694                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3695                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3696                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3697                              <1> 	;
  3698                              <1> 	; Retro UNIX 8086 v1 modification: 
  3699                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3700                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3701                              <1> 	;
  3702                              <1> 	; Retro UNIX 8086 v1 feature only!
  3703                              <1> 	;	Using purpose: Kernel will start without time-out
  3704                              <1> 	;	(internal clock/timer) functionality.
  3705                              <1> 	;	Then etc/init will enable clock/timer for
  3706                              <1> 	;	multi tasking. (Then it will not be disabled again
  3707                              <1> 	;	except hardware reset/restart.)
  3708                              <1> 	;
  3709                              <1> 
  3710 000041A9 803D[54700000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3711                              <1> 	;;ja	error
  3712                              <1> 	;ja	badsys ; 14/05/2015
  3713                              <1> 	; 24/12/2021
  3714 000041B0 7605                <1> 	jna	short emt_0 
  3715 000041B2 E980FBFFFF          <1> 	jmp	badsys
  3716                              <1> emt_0:
  3717                              <1> 	; 24/12/2021
  3718                              <1> 	;cli
  3719 000041B7 21DB                <1> 	and	ebx, ebx
  3720 000041B9 740F                <1> 	jz	short emt_2
  3721                              <1> 	; Enable multi tasking -time sharing-
  3722 000041BB B8[70500000]        <1> 	mov	eax, clock
  3723                              <1> emt_1:
  3724 000041C0 A3[D5070000]        <1> 	mov	[x_timer], eax
  3725                              <1> 	;sti
  3726 000041C5 E9DBFAFFFF          <1> 	jmp	sysret
  3727                              <1> emt_2:
  3728                              <1> 	; Disable multi tasking -time sharing-
  3729 000041CA B8[DD070000]        <1> 	mov	eax, u_timer
  3730 000041CF EBEF                <1> 	jmp	short emt_1
  3731                              <1> 
  3732                              <1> 	; Original UNIX v1 'sysemt' routine
  3733                              <1> ;sysemt:
  3734                              <1>         ;
  3735                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3736                              <1> 			 ; / in loc 30
  3737                              <1>         ;cmp    30,$core / was the argument a lower address 
  3738                              <1> 			; / than core
  3739                              <1>         ;blo    1f / yes, rtssym
  3740                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3741                              <1> 			; / and less than "ecore"
  3742                              <1>         ;blo    2f / yes, sysret2
  3743                              <1> ;1:
  3744                              <1>         ;mov    $rtssym,30
  3745                              <1> ;2:
  3746                              <1>         ;br     sysret2
  3747                              <1> 
  3748                              <1> sysilgins:
  3749                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3750                              <1> 	; 03/06/2013
  3751                              <1> 	; Retro UNIX 8086 v1 modification: 
  3752                              <1> 	;	not a valid system call ! (not in use)
  3753                              <1> 	;
  3754 000041D1 E961FBFFFF          <1> 	jmp	badsys
  3755                              <1> 	;jmp	error
  3756                              <1> 	;;jmp 	sysret
  3757                              <1> 
  3758                              <1> 	; Original UNIX v1 'sysemt' routine
  3759                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3760                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3761                              <1> 			  ;/ put it in loc 8.,
  3762                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3763                              <1> 		       ; / trap address
  3764                              <1>         ;blo    1f / is the address a user core address?  
  3765                              <1> 		; / yes, go to 2f
  3766                              <1>         ;cmp    10,$ecore
  3767                              <1>         ;blo    2f
  3768                              <1> ;1:
  3769                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3770                              <1> 		    ; / instruction trap address for the system
  3771                              <1> ;2:
  3772                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3773                              <1> 
  3774                              <1> sysmdate: ; < change the modification time of a file >
  3775                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3776                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3777                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3778                              <1> 	;
  3779                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3780                              <1> 	; file into core. The user is checked if he is the owner 
  3781                              <1> 	; or super user. If he is neither an error occurs.
  3782                              <1> 	; 'setimod' is then called to set the i-node modification
  3783                              <1> 	; byte and the modification time, but the modification time
  3784                              <1> 	; is overwritten by whatever get put on the stack during
  3785                              <1> 	; a 'systime' system call. This calls are restricted to
  3786                              <1> 	; the super user.		
  3787                              <1> 	;
  3788                              <1> 	; Calling sequence:
  3789                              <1> 	;	sysmdate; name
  3790                              <1> 	; Arguments:
  3791                              <1> 	;	name - points to the name of file
  3792                              <1> 	; Inputs: (arguments)
  3793                              <1> 	; Outputs: -
  3794                              <1> 	; ...............................................................
  3795                              <1> 	;				
  3796                              <1> 	; Retro UNIX 8086 v1 modification: 
  3797                              <1> 	;	 The user/application program puts address 
  3798                              <1> 	;	 of the file name in BX register 
  3799                              <1> 	;	 as 'sysmdate' system call argument.
  3800                              <1> 	;
  3801                              <1> ; / change the modification time of a file
  3802                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3803 000041D6 891D[20700000]      <1>         mov	[u.namep], ebx
  3804 000041DC E816090000          <1> 	call	namei
  3805                              <1> 		; jsr r0,namei / get its i-number
  3806                              <1> 	;;jc	error       
  3807                              <1> 	;	; br error2 / no, such file
  3808                              <1> 	;jc	fnotfound ; file not found !
  3809                              <1> 	; 24/12/2021
  3810 000041E1 7305                <1> 	jnc	short mdate_0
  3811 000041E3 E9BBFEFFFF          <1> 	jmp	fnotfound
  3812                              <1> mdate_0:
  3813 000041E8 E8DF100000          <1> 	call	iget
  3814                              <1> 		; jsr r0,iget / get i-node into core
  3815 000041ED A0[54700000]        <1> 	mov	al, [u.uid]
  3816 000041F2 3A05[D96C0000]      <1> 	cmp	al, [i.uid]
  3817                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3818 000041F8 7413                <1> 	je	short mdate_1
  3819                              <1>         	; beq 1f / yes
  3820 000041FA 20C0                <1> 	and	al, al
  3821                              <1> 		; tstb u.uid / no, is user the super user
  3822                              <1> 	;jnz	error
  3823                              <1> 		; bne error2 / no, error
  3824 000041FC 740F                <1> 	jz	short mdate_1
  3825 000041FE C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3825 00004206 0000                <1>
  3826 00004208 E978FAFFFF          <1> 	jmp	error
  3827                              <1> mdate_1: ;1:
  3828 0000420D E8C6110000          <1> 	call	setimod
  3829                              <1>         	; jsr r0,setimod / fill in modification data,
  3830                              <1> 		               ; / time etc.
  3831 00004212 BE[706C0000]        <1> 	mov	esi, p_time
  3832 00004217 BF[F06C0000]        <1> 	mov	edi, i.mtim
  3833 0000421C A5                  <1> 	movsd
  3834                              <1> 		; mov 4(sp),i.mtim / move present time to
  3835                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3836 0000421D E983FAFFFF          <1>         jmp	sysret
  3837                              <1> 		; br sysret2
  3838                              <1> 
  3839                              <1> sysstty: ; < set tty status and mode >
  3840                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3841                              <1> 	;	    ((32 bit reg push/pop))
  3842                              <1> 	; 17/11/2015
  3843                              <1> 	; 12/11/2015
  3844                              <1> 	; 29/10/2015
  3845                              <1> 	; 17/10/2015
  3846                              <1> 	; 13/10/2015
  3847                              <1> 	; 29/06/2015
  3848                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  3849                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  3850                              <1> 	;
  3851                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  3852                              <1> 	; whose file descriptor is in (u.r0).
  3853                              <1> 	;
  3854                              <1> 	; Calling sequence:
  3855                              <1> 	;	sysstty; arg
  3856                              <1> 	; Arguments:
  3857                              <1> 	;	arg - address of 3 consequitive words that contain
  3858                              <1> 	;	      the source of status data	
  3859                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  3860                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  3861                              <1> 	; ...............................................................
  3862                              <1> 	;	
  3863                              <1> 	; Retro UNIX 8086 v1 modification: 
  3864                              <1> 	;	'sysstty' system call will set the tty
  3865                              <1> 	;	(clear keyboard buffer and set cursor position)
  3866                              <1> 	;	 in following manner:
  3867                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  3868                              <1> 	;
  3869                              <1> 	; Inputs:
  3870                              <1> 	;	BX = 0 --> means
  3871                              <1> 	;	   If CL = FFh
  3872                              <1> 	;	      set cursor position for console tty, only 
  3873                              <1> 	;	      CH will be ignored (char. will not be written)	
  3874                              <1> 	;	   If CH = 0 (CL < FFh)
  3875                              <1> 	;	      set console tty for (current) process
  3876                              <1> 	;	      CL = tty number (0 to 9)
  3877                              <1> 	;	      (If CH = 0, character will not be written)			
  3878                              <1> 	;          If CH > 0 (CL < FFh)	
  3879                              <1> 	;             CL = tty number (0 to 9)
  3880                              <1> 	;	      CH = character will be written
  3881                              <1> 	;	        at requested cursor position (in DX)	
  3882                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  3883                              <1>   	;		(only tty number 0 to 7) 
  3884                              <1> 	;          DL = communication parameters (for serial ports) 
  3885                              <1> 	;	        (only for COM1 and COM2 serial ports)
  3886                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  3887                              <1> 	;			or set cursor position	
  3888                              <1> 	;	   DH = 0FFh -> DL is not valid
  3889                              <1> 	;		do not set serial port parameters 
  3890                              <1> 	;		or do not set cursor position
  3891                              <1> 	;
  3892                              <1> 	;	BX > 0 --> points to name of tty
  3893                              <1> 	;    	   CH > 0 -->
  3894                              <1> 	;		CH = character will be written in current 
  3895                              <1> 	;            	cursor position (for tty number from 0 to 7)
  3896                              <1> 	;	     	or character will be sent to serial port
  3897                              <1> 	;	     	(for tty number 8 or 9)
  3898                              <1> 	;		CL = color of the character if tty number < 8.
  3899                              <1> 	;    	   CH = 0 --> Do not write a character, 
  3900                              <1> 	;		set mode (tty 8 to 9) or 
  3901                              <1> 	;		set current cursor positions (tty 0 to 7) only. 
  3902                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  3903                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  3904                              <1> 	;		(DL is not valid)
  3905                              <1> 	;	   DL = communication parameters 
  3906                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  3907                              <1> 	; Outputs:
  3908                              <1> 	;	cf = 0 -> OK
  3909                              <1> 	;	     AL = tty number (0 to 9)
  3910                              <1> 	;	     AH = line status if tty number is 8 or 9
  3911                              <1> 	;	     AH = process number (of the caller) 	
  3912                              <1> 	;	cf = 1 means error (requested tty is not ready)
  3913                              <1> 	;	     AH = FFh if the tty is locked 
  3914                              <1> 	;		  (owned by another process)
  3915                              <1> 	;	        = process number (of the caller) 
  3916                              <1> 	;		  (if < FFh and tty number < 8)
  3917                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  3918                              <1> 	;	     AH = line status if tty number is 8 or 9
  3919                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  3920                              <1> 	;
  3921                              <1> 	; 27/06/2015 (32 bit modifications)
  3922                              <1> 	; 14/01/2014
  3923 00004222 31C0                <1> 	xor 	eax, eax
  3924 00004224 6648                <1> 	dec	ax ; 17/10/2015
  3925 00004226 A3[08700000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  3926 0000422B 21DB                <1> 	and	ebx, ebx
  3927                              <1>         ;jnz	sysstty_6
  3928                              <1> 	; 24/12/2021
  3929 0000422D 7405                <1> 	jz	short sysstty_14
  3930 0000422F E9C7000000          <1> 	jmp	sysstty_6
  3931                              <1> sysstty_14:
  3932                              <1> 	; set console tty
  3933                              <1> 	; 29/10/2015
  3934                              <1> 	; 17/01/2014 
  3935 00004234 80F909              <1> 	cmp	cl, 9
  3936 00004237 7613                <1> 	jna	short sysstty_0
  3937                              <1> 	; 17/11/2015
  3938 00004239 80F9FF              <1> 	cmp	cl, 0FFh
  3939 0000423C 7202                <1> 	jb	short sysstty_13
  3940 0000423E 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  3941                              <1> sysstty_13:
  3942 00004240 8A1D[57700000]      <1> 	mov	bl, [u.uno] ; process number
  3943 00004246 8A8B[556D0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  3944                              <1> sysstty_0:
  3945                              <1> 	; 29/06/2015
  3946 0000424C 52                  <1> 	push	edx ; 24/12/2021
  3947 0000424D 51                  <1> 	push	ecx
  3948 0000424E 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  3949 00004250 88C8                <1> 	mov	al, cl
  3950 00004252 A2[08700000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  3951 00004257 E875180000          <1> 	call	ottyp
  3952 0000425C 59                  <1> 	pop	ecx
  3953 0000425D 5A                  <1> 	pop	edx
  3954                              <1> 	;
  3955 0000425E 7256                <1> 	jc	short sysstty_pd_err
  3956                              <1> 	;
  3957 00004260 80F908              <1> 	cmp	cl, 8
  3958 00004263 7220                <1> 	jb	short sysstty_2
  3959                              <1> 	;
  3960 00004265 80FEFF              <1> 	cmp	dh, 0FFh
  3961 00004268 741B                <1> 	je	short sysstty_2
  3962                              <1> 	; set communication parameters for serial ports
  3963                              <1> 	; 29/10/2015
  3964 0000426A 88D4                <1> 	mov	ah, dl ; communication parameters
  3965                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  3966                              <1> 		;			 THRE int + RDA int 
  3967                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  3968                              <1> 		;			 THRE int + RDA int 
  3969 0000426C 28C0                <1> 	sub	al, al ; 0
  3970                              <1> 	; 12/07/2014
  3971 0000426E 80F909              <1> 	cmp	cl, 9
  3972 00004271 7202                <1> 	jb	short sysstty_1
  3973 00004273 FEC0                <1> 	inc	al
  3974                              <1> sysstty_1:
  3975 00004275 51                  <1> 	push	ecx ; 24/12/2021
  3976                              <1> 	; 29/06/2015	
  3977 00004276 E8B5F4FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  3978 0000427B 66890D[09700000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  3979                              <1> 			     ; Modem status (EAX bits 16 to 23)
  3980 00004282 59                  <1> 	pop	ecx
  3981 00004283 7267                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  3982                              <1> sysstty_2:
  3983                              <1> 	; 17/01/2014
  3984 00004285 20ED                <1> 	and	ch, ch 	; set cursor position 
  3985                              <1> 			; or comm. parameters ONLY
  3986 00004287 750D                <1> 	jnz	short sysstty_3
  3987 00004289 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  3988 00004290 888B[556D0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  3989                              <1> sysstty_3:
  3990                              <1> 	; 16/01/2014
  3991 00004296 88E8                <1> 	mov	al, ch ; character  ; 0 to FFh
  3992                              <1> 	; 17/11/2015
  3993 00004298 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  3994 0000429A 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  3995                              <1>         ;jna	sysstty_9
  3996                              <1> 	; 24/12/2021
  3997 0000429C 7705                <1> 	ja	short sysstty_12
  3998 0000429E E9BE000000          <1> 	jmp	sysstty_9
  3999                              <1> sysstty_12:
  4000                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4001                              <1> 	; (Set specified serial port as console tty port)
  4002                              <1> 	; CH = character to be written
  4003                              <1> 	; 15/04/2014
  4004                              <1> 	; CH = 0 --> initialization only
  4005                              <1> 	; AL = character
  4006                              <1> 	; 26/06/2014
  4007 000042A3 880D[5C700000]      <1> 	mov	[u.ttyn], cl
  4008                              <1> 	; 12/07/2014
  4009 000042A9 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4010 000042AB 20C0                <1> 	and	al, al
  4011 000042AD 7416                <1> 	jz	short sysstty_4 ; al = ch = 0
  4012                              <1>  	; 04/07/2014
  4013 000042AF E8371E0000          <1> 	call 	sndc
  4014                              <1> 	; 12/07/2014
  4015 000042B4 EB1B                <1> 	jmp	short sysstty_5
  4016                              <1> sysstty_pd_err: ; 29/06/2015
  4017                              <1> 	; 'permission denied !' error
  4018 000042B6 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4018 000042BE 0000                <1>
  4019 000042C0 E9C0F9FFFF          <1> 	jmp	error
  4020                              <1> sysstty_4:
  4021                              <1> 	; 12/07/2014
  4022                              <1> 	;xchg 	ah, al	; al = 0 -> al = ah, ah = 0
  4023 000042C5 88E0                <1> 	mov	al, ah ; 29/06/2015
  4024 000042C7 2C08                <1> 	sub	al, 8
  4025                              <1> 	; 27/06/2015
  4026 000042C9 E85AF4FFFF          <1> 	call	sp_status ; get serial port status
  4027                              <1> 	; AL = Line status, AH = Modem status
  4028                              <1> 	; 12/11/2015
  4029 000042CE 3C80                <1> 	cmp	al, 80h
  4030 000042D0 F5                  <1> 	cmc
  4031                              <1> sysstty_5:
  4032 000042D1 66A3[09700000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4033                              <1> 		     ; EAX bits 16-23 = modem status	
  4034 000042D7 9C                  <1> 	pushf
  4035 000042D8 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4036 000042DA A0[5C700000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4037 000042DF E800190000          <1> 	call	cttyp
  4038 000042E4 9D                  <1> 	popf
  4039                              <1> 	;jnc	sysret	
  4040                              <1> 	; 24/12/2021
  4041 000042E5 7205                <1> 	jc	short sysstty_tmout_err
  4042 000042E7 E9B9F9FFFF          <1> 	jmp	sysret
  4043                              <1> 	; time out error 
  4044                              <1> sysstty_tmout_err:
  4045 000042EC C705[5D700000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4045 000042F4 0000                <1>
  4046 000042F6 E98AF9FFFF          <1> 	jmp	error
  4047                              <1> sysstty_6:
  4048 000042FB 52                  <1> 	push	edx ; 24/12/2021
  4049 000042FC 51                  <1> 	push	ecx
  4050 000042FD 891D[20700000]      <1> 	mov	[u.namep], ebx
  4051 00004303 E8EF070000          <1> 	call	namei
  4052 00004308 59                  <1> 	pop	ecx
  4053 00004309 5A                  <1> 	pop	edx
  4054 0000430A 720E                <1> 	jc	short sysstty_inv_dn
  4055                              <1> 	;
  4056 0000430C 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4057 00004310 7708                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4058                              <1> 	;
  4059 00004312 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4060                              <1> 		       ; /dev/COM1, /dev/COM2
  4061 00004314 7213                <1> 	jb	short sysstty_7
  4062 00004316 2C0A                <1> 	sub	al, 10
  4063 00004318 EB20                <1> 	jmp	short sysstty_8
  4064                              <1> sysstty_inv_dn: 
  4065                              <1> 	; 27/06/2015
  4066                              <1> 	; Invalid device name (not a tty) ! error
  4067                              <1> 	; (Device is not a tty or device name not found)
  4068 0000431A C705[5D700000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4068 00004322 0000                <1>
  4069 00004324 E95CF9FFFF          <1> 	jmp	error 
  4070                              <1> sysstty_7:
  4071 00004329 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4072 0000432B 75ED                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4073 0000432D 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4074 00004334 8A83[556D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4075                              <1> sysstty_8:	
  4076 0000433A A2[08700000]        <1> 	mov	[u.r0], al
  4077 0000433F 52                  <1> 	push	edx ; 24/12/2021
  4078 00004340 50                  <1> 	push	eax
  4079 00004341 51                  <1> 	push	ecx	
  4080 00004342 E88A170000          <1> 	call	ottyp
  4081 00004347 59                  <1> 	pop	ecx
  4082 00004348 58                  <1> 	pop	eax
  4083 00004349 5A                  <1> 	pop	edx
  4084                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4085                              <1> 	; 24/12/2021
  4086 0000434A 7305                <1> 	jnc	short sysstty_15
  4087                              <1> 	; 'permission denied !'
  4088 0000434C E965FFFFFF          <1> 	jmp	sysstty_pd_err
  4089                              <1> sysstty_15:
  4090                              <1> 	; 29/10/2015
  4091 00004351 86E9                <1> 	xchg 	ch, cl
  4092                              <1> 		; cl = character, ch = color code
  4093 00004353 86C1                <1> 	xchg	al, cl
  4094                              <1> 		; al = character, cl = tty number
  4095 00004355 80F907              <1> 	cmp	cl, 7
  4096                              <1> 	;ja	sysstty_12
  4097                              <1> 	; 24/12/2021
  4098 00004358 7605                <1> 	jna	short sysstty_16
  4099 0000435A E944FFFFFF          <1> 	jmp	sysstty_12
  4100                              <1> sysstty_16:
  4101                              <1> 	; 16/01/2014
  4102 0000435F 30FF                <1> 	xor	bh, bh
  4103                              <1> 	;
  4104                              <1> sysstty_9: 	; tty 0 to tty 7
  4105                              <1> 	; al = character
  4106 00004361 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4107 00004364 740B                <1> 	je	short sysstty_10
  4108 00004366 51                  <1> 	push	ecx ; 24/12/2021
  4109 00004367 50                  <1> 	push	eax	
  4110                              <1> 	;movzx, ebx, cl
  4111 00004368 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4112 0000436A E83BD2FFFF          <1> 	call	set_cpos
  4113 0000436F 58                  <1> 	pop	eax
  4114 00004370 59                  <1> 	pop	ecx
  4115                              <1> sysstty_10: 
  4116                              <1> 	; 29/10/2015
  4117 00004371 08C0                <1> 	or	al, al ; character
  4118 00004373 740D                <1> 	jz      short sysstty_11 ; al = 0
  4119                              <1> 	; 17/11/2015
  4120 00004375 3CFF                <1> 	cmp	al, 0FFh
  4121 00004377 7309                <1> 	jnb	short sysstty_11
  4122                              <1> 		; ch > 0 and ch < FFh
  4123                              <1> 	; write a character at current cursor position
  4124 00004379 88EC                <1> 	mov	ah, ch ; color/attribute
  4125                              <1> 	; 12/07/2014
  4126 0000437B 51                  <1> 	push	ecx ; 24/12/2021
  4127 0000437C E867D3FFFF          <1> 	call	write_c_current
  4128 00004381 59                  <1> 	pop	ecx
  4129                              <1> sysstty_11:
  4130                              <1> 	; 14/01/2014
  4131 00004382 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4132                              <1> 	; 18/01/2014
  4133                              <1> 	;movzx	eax, cl ; 27/06/2015
  4134 00004384 88C8                <1> 	mov	al, cl
  4135 00004386 E859180000          <1> 	call	cttyp
  4136 0000438B E915F9FFFF          <1> 	jmp	sysret
  4137                              <1> 
  4138                              <1> ; Original UNIX v1 'sysstty' routine:
  4139                              <1> ; gtty:
  4140                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4141                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4142                              <1> 	; 		/ r2 has source
  4143                              <1>         ;mov    r2,-(sp)
  4144                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4145                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4146                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4147                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4148                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4149                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4150                              <1>         ;       br .+4 / list empty, skip branch
  4151                              <1>         ;br     1b / get another character until list is empty
  4152                              <1>         ;mov    0b,r1 / move cc offset to r1
  4153                              <1>         ;inc    r1 / bump it for output clist
  4154                              <1>         ;tstb   cc(r1) / is it 0
  4155                              <1>         ;beq    1f / yes, no characters to output
  4156                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4157                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4158                              <1>         ;br     1b / try to calm it down again
  4159                              <1> ;1:
  4160                              <1>         ;mov    (sp)+,r1
  4161                              <1>         ;mov    (sp)+,r2 / restore registers
  4162                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4163                              <1>         ;beq    1f / if 0, 1f
  4164                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4165                              <1>         ;                   / control status register
  4166                              <1> ;1:
  4167                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4168                              <1>         ;beq    1f / if 0 1f
  4169                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4170                              <1> 	;		    / control status reg
  4171                              <1> ;1:
  4172                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4173                              <1>         ;jmp     sysret2 / return to user
  4174                              <1> 
  4175                              <1> sysgtty: ; < get tty status >
  4176                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4177                              <1> 	;	    ((32 bit reg push/pop))
  4178                              <1> 	; 23/11/2015
  4179                              <1> 	; 29/10/2015
  4180                              <1> 	; 17/10/2015
  4181                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4182                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4183                              <1> 	;
  4184                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4185                              <1> 	; It stores in the three words addressed by it's argument
  4186                              <1> 	; the status of the typewriter whose file descriptor
  4187                              <1> 	; in (u.r0).
  4188                              <1> 	;
  4189                              <1> 	; Calling sequence:
  4190                              <1> 	;	sysgtty; arg
  4191                              <1> 	; Arguments:
  4192                              <1> 	;	arg - address of 3 words destination of the status
  4193                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4194                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4195                              <1> 	; ...............................................................
  4196                              <1> 	;	
  4197                              <1> 	; Retro UNIX 8086 v1 modification: 
  4198                              <1> 	;	'sysgtty' system call will return status of tty
  4199                              <1> 	;	(keyboard, serial port and video page status)
  4200                              <1> 	;	 in following manner:
  4201                              <1> 	;
  4202                              <1> 	; Inputs:
  4203                              <1> 	;	BX = 0 --> means 
  4204                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4205                              <1> 	;	                 for (current) process
  4206                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4207                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4208                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4209                              <1> 	;	     CH > 0 -->	tty number + 1
  4210                              <1> 	;
  4211                              <1> 	;	BX > 0 --> points to name of tty
  4212                              <1> 	;	     CL = 0 --> return keyboard status
  4213                              <1> 	;	     CL = 1 --> return video page status
  4214                              <1> 	;	     CH = undefined		 
  4215                              <1> 	;
  4216                              <1> 	; Outputs:
  4217                              <1> 	;	cf = 0 ->
  4218                              <1> 	;
  4219                              <1> 	;	     AL = tty number from 0 to 9
  4220                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4221                              <1> 	;	     AH = 0 if the tty is free/unused
  4222                              <1> 	;	     AH = the process number of the caller 
  4223                              <1>  	;	     AH = FFh if the tty is locked by another process
  4224                              <1> 	;
  4225                              <1> 	;	  (if calling is for serial port status)
  4226                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4227                              <1> 	;		  (BH = modem status, BL = Line status)
  4228                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4229                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4230                              <1> 	;
  4231                              <1> 	;	  (if calling is for keyboard status)
  4232                              <1> 	;	     BX = current character in tty/keyboard buffer
  4233                              <1> 	;		  (BH = scan code, BL = ascii code)
  4234                              <1> 	;		  (BX=0 if there is not a waiting character)
  4235                              <1> 	;	     CX  is undefined
  4236                              <1> 	;
  4237                              <1> 	;	  (if calling is for video page status)	
  4238                              <1> 	;	     BX = cursor position on the video page
  4239                              <1> 	;		  if tty number < 8
  4240                              <1> 	;		  (BH = row, BL = column)
  4241                              <1> 	;	     CX = current character (in cursor position)
  4242                              <1> 	;		  on the video page of the tty 
  4243                              <1> 	;		  if tty number < 8
  4244                              <1> 	;		  (CH = color, CL = character)
  4245                              <1> 	;	
  4246                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4247                              <1> 	;
  4248                              <1> 	;	     AH = FFh if the caller is not owner of
  4249                              <1> 	;		  specified tty or console tty
  4250                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4251                              <1> 	;	     BX, CX are undefined if cf = 1
  4252                              <1> 	;
  4253                              <1> 	;	  (If tty number is 8 or 9)
  4254                              <1> 	;	     AL = tty number 
  4255                              <1> 	;	     AH = the process number of the caller 
  4256                              <1> 	;	     BX = serial port status
  4257                              <1> 	;  		 (BH = modem status, BL = Line status)
  4258                              <1> 	;	     CX = 0
  4259                              <1> 	;
  4260                              <1> 		
  4261                              <1> gtty:   ; get (requested) tty number
  4262                              <1> 	; 17/10/2015
  4263                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4264                              <1> 	; 30/05/2013 - 12/07/2014
  4265                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4266                              <1> 	;
  4267                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4268                              <1> 	;
  4269                              <1> 	; 28/06/2015 (32 bit modifications)
  4270                              <1> 	; 16/01/2014
  4271 00004390 31C0                <1> 	xor 	eax, eax
  4272 00004392 6648                <1> 	dec	ax ; 17/10/2015
  4273 00004394 A3[08700000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4274 00004399 80F901              <1> 	cmp	cl, 1
  4275 0000439C 760F                <1> 	jna	short sysgtty_0
  4276                              <1> sysgtty_invp:
  4277                              <1> 	; 28/06/2015
  4278 0000439E C705[5D700000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4278 000043A6 0000                <1>
  4279 000043A8 E9D8F8FFFF          <1> 	jmp	error
  4280                              <1> sysgtty_0:	
  4281 000043AD 21DB                <1> 	and	ebx, ebx
  4282 000043AF 742E                <1> 	jz	short sysgtty_1
  4283                              <1> 	;
  4284 000043B1 891D[20700000]      <1> 	mov	[u.namep], ebx
  4285                              <1> 	;push	cx ; 23/11/2015
  4286 000043B7 51                  <1> 	push	ecx ; 24/12/2021
  4287 000043B8 E83A070000          <1> 	call	namei
  4288 000043BD 59                  <1> 	pop	ecx
  4289                              <1> 	;pop	cx ; 23/11/2015
  4290 000043BE 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4291                              <1> 	;
  4292 000043C0 6683F801            <1> 	cmp	ax, 1
  4293 000043C4 7622                <1> 	jna	short sysgtty_2
  4294 000043C6 6683E80A            <1> 	sub	ax, 10
  4295 000043CA 6683F809            <1> 	cmp	ax, 9
  4296                              <1> 	;ja	short sysgtty_inv_dn
  4297                              <1> 	;mov	ch, al
  4298                              <1> 	;jmp	short sysgtty_4
  4299                              <1> 	; 23/11/2015
  4300 000043CE 7629                <1> 	jna	short sysgtty_4
  4301                              <1> sysgtty_inv_dn: 
  4302                              <1> 	; 28/06/2015
  4303                              <1> 	; Invalid device name (not a tty) ! error
  4304                              <1> 	; (Device is not a tty or device name not found)
  4305 000043D0 C705[5D700000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4305 000043D8 0000                <1>
  4306 000043DA E9A6F8FFFF          <1> 	jmp	error 
  4307                              <1> sysgtty_1:
  4308                              <1> 	; 16/01/2014
  4309 000043DF 80FD0A              <1> 	cmp	ch, 10
  4310 000043E2 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4311 000043E4 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4312 000043E6 790F                <1> 	jns	short sysgtty_3 ; not negative
  4313                              <1> 	;
  4314                              <1> sysgtty_2:
  4315                              <1> 	; get tty number of console tty
  4316 000043E8 8A25[57700000]      <1> 	mov	ah, [u.uno]
  4317                              <1>  	; 28/06/2015
  4318 000043EE 0FB6DC              <1> 	movzx 	ebx, ah
  4319 000043F1 8AAB[556D0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4320                              <1> sysgtty_3:
  4321 000043F7 88E8                <1> 	mov	al, ch
  4322                              <1> sysgtty_4:
  4323 000043F9 A2[08700000]        <1> 	mov	[u.r0], al
  4324                              <1>  	; 28/06/2015
  4325                              <1> 	;cmp	al, 9
  4326                              <1> 	;ja	short sysgtty_invp
  4327 000043FE 8B2D[04700000]      <1> 	mov	ebp, [u.usp]
  4328                              <1> 	; 23/11/2015
  4329 00004404 20C9                <1> 	and	cl, cl
  4330 00004406 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4331 00004408 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4332 0000440A 722E                <1> 	jb	short sysgtty_6 ; video page status
  4333                              <1> 	; serial port status
  4334                              <1> 	; 12/07/2014
  4335                              <1> 	;mov	dx, 0
  4336                              <1> 	;je	short sysgtty_5
  4337                              <1> 	;inc	dl
  4338                              <1> ;sysgtty_5:
  4339                              <1> 	; 28/06/2015
  4340 0000440C 2C08                <1> 	sub	al, 8
  4341 0000440E E815F3FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4342                              <1> 	; AL = Line status, AH = Modem status
  4343 00004413 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4344 00004417 8A25[57700000]      <1> 	mov	ah, [u.uno]
  4345 0000441D 8825[09700000]      <1>         mov     [u.r0+1], ah
  4346                              <1> 	; 24/12/2021
  4347 00004423 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4348                              <1> 				; (in ECX)
  4349 00004429 A880                <1> 	test	al, 80h
  4350 0000442B 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4351 0000442D A801                <1> 	test	al, 1
  4352                              <1> 	;jz	sysret
  4353 0000442F 7404                <1> 	jz	short sysgtty_10
  4354 00004431 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4355                              <1> sysgtty_10:
  4356 00004435 E96BF8FFFF          <1> 	jmp	sysret
  4357                              <1> sysgtty_6:
  4358 0000443A A2[5C700000]        <1> 	mov	[u.ttyn], al ; tty number
  4359                              <1> 	;movzx	ebx, al
  4360 0000443F 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4361 00004441 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4362                              <1> 	; 22/04/2014 - 29/06/2015
  4363 00004443 81C3[746C0000]      <1>         add     ebx, ttyl
  4364 00004449 8A23                <1>  	mov	ah, [ebx]
  4365 0000444B 3A25[57700000]      <1> 	cmp	ah, [u.uno]
  4366 00004451 7404                <1> 	je	short sysgtty_7
  4367 00004453 20E4                <1> 	and	ah, ah
  4368                              <1> 	;jz	short sysgtty_7
  4369 00004455 7506                <1> 	jnz	short sysgtty_8
  4370                              <1> 	;mov	ah, 0FFh
  4371                              <1> sysgtty_7:
  4372 00004457 8825[09700000]      <1>         mov     [u.r0+1], ah
  4373                              <1> sysgtty_8:
  4374 0000445D 08C9                <1> 	or	cl, cl
  4375 0000445F 7510                <1> 	jnz	short sysgtty_9
  4376 00004461 B001                <1> 	mov	al, 1  ; test a key is available
  4377 00004463 E8061C0000          <1> 	call	getc
  4378 00004468 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4379 0000446C E934F8FFFF          <1> 	jmp	sysret
  4380                              <1> sysgtty_9:
  4381 00004471 8A1D[5C700000]      <1> 	mov	bl, [u.ttyn]
  4382                              <1> 	; bl = video page number
  4383 00004477 E8651D0000          <1> 	call 	get_cpos
  4384                              <1> 	; dx = cursor position
  4385 0000447C 66895510            <1> 	mov	[ebp+16], dx ; bx
  4386                              <1> 	;mov	bl, [u.ttyn]
  4387                              <1> 	; bl = video page number
  4388 00004480 E86D1D0000          <1> 	call	read_ac_current
  4389                              <1> 	; ax = character and attribute/color
  4390 00004485 66894518            <1> 	mov	[ebp+24], ax ; cx
  4391 00004489 E917F8FFFF          <1> 	jmp	sysret
  4392                              <1> sysgtty_dnr_err:
  4393                              <1> 	; 'device not responding !' error	
  4394                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4395 0000448E C705[5D700000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4395 00004496 0000                <1>
  4396 00004498 E9E8F7FFFF          <1> 	jmp	error	
  4397                              <1> 
  4398                              <1> ; Original UNIX v1 'sysgtty' routine:
  4399                              <1> ; sysgtty:
  4400                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4401                              <1> 	;	       / r2 has destination
  4402                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4403                              <1> 	;                     / in 1st word of dest
  4404                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4405                              <1> 	;                     / in 2nd word of dest
  4406                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4407                              <1>         ;jmp    sysret2 / return to user
  4408                              <1> 	
  4409                              <1> ; Original UNIX v1 'gtty' routine:
  4410                              <1> ; gtty:
  4411                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4412                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4413                              <1>         ;jsr    r0,getf / get the i-number of the file
  4414                              <1>         ;tst    r1 / is it open for reading
  4415                              <1>         ;bgt    1f / yes
  4416                              <1>         ;neg    r1 / no, i-number is negative, 
  4417                              <1> 	;          / so make it positive
  4418                              <1> ;1:
  4419                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4420                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4421                              <1>         ;bhis   error9 / no, error
  4422                              <1>         ;asl    r1 / 0%2
  4423                              <1>         ;asl    r1 / 0%4 / yes
  4424                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4425                              <1> 	;	       ; / tty block
  4426                              <1>         ;mov    u.off,r2 / put argument in r2
  4427                              <1>         ;rts    r0 / return
  1994                                  %include 'u2.s'        ; 11/05/2015
  1995                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS2.INC
  1996                              <1> ; Last Modification: 24/12/2021
  1997                              <1> ; ----------------------------------------------------------------------------
  1998                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  1999                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2000                              <1> ;
  2001                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2002                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2003                              <1> ; <Bell Laboratories (17/3/1972)>
  2004                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2005                              <1> ;
  2006                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2007                              <1> ;
  2008                              <1> ; ****************************************************************************
  2009                              <1> 
  2010                              <1> syslink:
  2011                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2012                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2013                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2014                              <1> 	;
  2015                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2016                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2017                              <1> 	; given to the entry that will go in the current directory.
  2018                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2019                              <1> 	; in the name 2 entry of current directory is the same
  2020                              <1> 	; i-number for the name 1 file.
  2021                              <1> 	;
  2022                              <1> 	; Calling sequence:
  2023                              <1> 	;	syslink; name 1; name 2
  2024                              <1> 	; Arguments:
  2025                              <1> 	;	name 1 - file name to which link will be created.
  2026                              <1> 	;	name 2 - name of entry in current directory that
  2027                              <1> 	;		 links to name 1.
  2028                              <1> 	; Inputs: -
  2029                              <1> 	; Outputs: -
  2030                              <1> 	; ...............................................................
  2031                              <1> 	;	
  2032                              <1> 	; Retro UNIX 8086 v1 modification: 
  2033                              <1> 	;       'syslink' system call has two arguments; so,
  2034                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2035                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2036                              <1> 	;
  2037                              <1> 		; / name1, name2
  2038                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2039 0000449D 891D[20700000]      <1> 	mov	[u.namep], ebx
  2040 000044A3 51                  <1> 	push	ecx
  2041 000044A4 E84E060000          <1> 	call	namei
  2042                              <1> 		; jsr r0,namei / find the i-number associated with
  2043                              <1> 			     ; / the 1st path name
  2044                              <1>      	;;and	ax, ax
  2045                              <1> 	;;jz	error ; File not found
  2046                              <1> 	;jc	error 
  2047                              <1> 		; br error9 / cannot be found
  2048 000044A9 730F                <1> 	jnc	short syslink0
  2049                              <1> 	;pop 	ecx
  2050                              <1> 	; 'file not found !' error
  2051 000044AB C705[5D700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2051 000044B3 0000                <1>
  2052 000044B5 E9CBF7FFFF          <1> 	jmp	error
  2053                              <1> syslink0:
  2054 000044BA E80D0E0000          <1> 	call	iget
  2055                              <1> 		; jsr r0,iget / get the i-node into core
  2056 000044BF 8F05[20700000]      <1> 	pop	dword [u.namep] ; ecx
  2057                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2058                              <1> 	; 24/12/2021
  2059 000044C5 50                  <1> 	push	eax ; *
  2060                              <1> 	;push	ax
  2061                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2062                              <1> 			    ; / (a link to this file is to be created)
  2063                              <1> 	; 24/12/2021
  2064 000044C6 8A0D[EE6F0000]      <1> 	mov	cl, [cdev]
  2065 000044CC 51                  <1> 	push	ecx ; **
  2066                              <1> 	;push	word [cdev]
  2067                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2068 000044CD E852000000          <1> 	call	isdir
  2069                              <1> 		; jsr r0,isdir / is it a directory
  2070 000044D2 E820060000          <1> 	call	namei
  2071                              <1> 		; jsr r0,namei / no, get i-number of name2
  2072                              <1> 	;jnc	error
  2073                              <1> 		; br .+4   / not found 
  2074                              <1> 			 ; / so r1 = i-number of current directory
  2075                              <1> 			 ; / ii = i-number of current directory
  2076                              <1> 		; br error9 / file already exists., error
  2077 000044D7 720F                <1> 	jc	short syslink1
  2078                              <1> 	; pop eax ; 24/12/2021
  2079                              <1> 	; pop eax
  2080                              <1> 	; 'file exists !' error
  2081 000044D9 C705[5D700000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2081 000044E1 0000                <1>
  2082 000044E3 E99DF7FFFF          <1> 	jmp	error
  2083                              <1> syslink1:
  2084                              <1> 	;pop	cx
  2085                              <1> 	; 24/12/2021
  2086 000044E8 59                  <1> 	pop	ecx ; **
  2087                              <1> 	;cmp	cx, [cdev]
  2088 000044E9 3A0D[EE6F0000]      <1> 	cmp	cl, [cdev]
  2089                              <1> 	;jne	error
  2090                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2091                              <1> 			       ; / end of current directory
  2092                              <1> 	        ; bne error9
  2093 000044EF 740F                <1> 	je	short syslink2
  2094                              <1> 	; 'not same drive !' error
  2095 000044F1 C705[5D700000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2095 000044F9 0000                <1>
  2096 000044FB E985F7FFFF          <1> 	jmp	error
  2097                              <1> syslink2:
  2098                              <1> 	;pop	eax ; 24/12/2021
  2099                              <1> 	;push	eax
  2100                              <1> 	; 24/12/2021
  2101 00004500 8B0424              <1> 	mov	eax, [esp] ; *
  2102 00004503 66A3[3A700000]      <1> 	mov	[u.dirbuf], ax
  2103                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2104 00004509 E8A0000000          <1> 	call	mkdir
  2105                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2106                              <1> 		 	     ; / in current directory
  2107                              <1> 	; 24/12/2021
  2108 0000450E 58                  <1> 	pop	eax ; *
  2109                              <1> 	;pop	ax
  2110                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2111 0000450F E8B80D0000          <1> 	call	iget
  2112                              <1> 		; jsr r0,iget / get i-node into core
  2113 00004514 FE05[D86C0000]      <1> 	inc	byte [i.nlks]
  2114                              <1> 		; incb i.nlks / add 1 to its number of links
  2115 0000451A E8B90E0000          <1> 	call	setimod
  2116                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2117 0000451F E981F7FFFF          <1> 	jmp	sysret
  2118                              <1> 
  2119                              <1> isdir:
  2120                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2121                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2122                              <1> 	;
  2123                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2124                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2125                              <1> 	;  called by syslink and sysunlink to make sure directories
  2126                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2127                              <1> 	; 'isdir' does not bother checking. The current i-node
  2128                              <1> 	;  is not disturbed.			
  2129                              <1> 	;		
  2130                              <1> 	; INPUTS ->
  2131                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2132                              <1> 	;    u.uid - user id
  2133                              <1> 	; OUTPUTS ->
  2134                              <1> 	;    r1 - contains current i-number upon exit
  2135                              <1> 	;    	 (current i-node back in core) 
  2136                              <1> 	;	
  2137                              <1> 	; ((AX = R1))
  2138                              <1> 	;
  2139                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2140                              <1> 	;
  2141                              <1> 
  2142                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2143                              <1> 	; / there is an error unless super user made the call
  2144                              <1> 	
  2145 00004524 803D[54700000]00    <1> 	cmp	byte [u.uid], 0 
  2146                              <1> 		; tstb u.uid / super user
  2147 0000452B 762D                <1> 	jna	short isdir1
  2148                              <1> 		; beq 1f / yes, don't care
  2149 0000452D 66FF35[EA6F0000]    <1> 	push	word [ii]
  2150                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2151 00004534 E8930D0000          <1> 	call	iget
  2152                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2153 00004539 66F705[D66C0000]00- <1> 	test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2153 00004541 40                  <1>
  2154                              <1> 		; bit $40000,i.flgs / is it a directory
  2155                              <1> 	;jnz	error
  2156                              <1> 		; bne error9 / yes, error
  2157 00004542 740F                <1> 	jz	short isdir0
  2158 00004544 C705[5D700000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2158 0000454C 0000                <1>
  2159                              <1> 				; 'permission denied !' error
  2160                              <1> 	; pop	ax
  2161 0000454E E932F7FFFF          <1> 	jmp	error	
  2162                              <1> isdir0:	
  2163 00004553 6658                <1> 	pop	ax
  2164                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2165 00004555 E8720D0000          <1> 	call	iget
  2166                              <1> 		; jsr r0,iget / get it back in
  2167                              <1> isdir1: ; 1:
  2168 0000455A C3                  <1> 	retn
  2169                              <1> 		; rts r0
  2170                              <1> 
  2171                              <1> sysunlink:
  2172                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2173                              <1> 	; 04/12/2015 (14 byte file names)
  2174                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2175                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2176                              <1> 	;
  2177                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2178                              <1> 	; name from its directory. If this entry was the last link
  2179                              <1> 	; to the file, the contents of the file are freed and the
  2180                              <1> 	; file is destroyed. If, however, the file was open in any
  2181                              <1> 	; process, the actual destruction is delayed until it is 
  2182                              <1> 	; closed, even though the directory entry has disappeared.
  2183                              <1> 	; 
  2184                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2185                              <1> 	; does not exist or that its directory can not be written.
  2186                              <1> 	; Write permission is not required on the file itself.
  2187                              <1> 	; It is also illegal to unlink a directory (except for
  2188                              <1> 	; the superuser).
  2189                              <1> 	;
  2190                              <1> 	; Calling sequence:
  2191                              <1> 	;	sysunlink; name
  2192                              <1> 	; Arguments:
  2193                              <1> 	;	name - name of directory entry to be removed 
  2194                              <1> 	; Inputs: -
  2195                              <1> 	; Outputs: -
  2196                              <1> 	; ...............................................................
  2197                              <1> 	;				
  2198                              <1> 	; Retro UNIX 8086 v1 modification:
  2199                              <1> 	;	 The user/application program puts address of the name
  2200                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2201                              <1> 
  2202                              <1> 	; / name - remove link name
  2203 0000455B 891D[20700000]      <1> 	mov	[u.namep], ebx
  2204                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2205 00004561 E891050000          <1> 	call	namei
  2206                              <1> 		; jsr r0,namei / find the i-number associated 
  2207                              <1> 			     ; / with the path name
  2208                              <1> 	;jc	error
  2209                              <1> 		; br error9 / not found
  2210 00004566 730F                <1> 	jnc	short sysunlink1
  2211                              <1> 	; 'file not found !' error
  2212 00004568 C705[5D700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2212 00004570 0000                <1>
  2213 00004572 E90EF7FFFF          <1> 	jmp	error
  2214                              <1> sysunlink1:
  2215 00004577 50                  <1> 	push	eax ; 24/12/2021
  2216                              <1> 	;push	ax
  2217                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2218 00004578 E8A7FFFFFF          <1> 	call	isdir
  2219                              <1> 		; jsr r0,isdir / is it a directory
  2220                              <1> 	;xor 	ax, ax
  2221                              <1> 	; 24/12/2021
  2222 0000457D 31C0                <1> 	xor	eax, eax
  2223 0000457F 66A3[3A700000]      <1> 	mov	[u.dirbuf], ax ; 0
  2224                              <1> 		; clr u.dirbuf / no, clear the location that will
  2225                              <1> 			   ; / get written into the i-number portion
  2226                              <1> 			 ; / of the entry
  2227 00004585 832D[24700000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2228                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2229 0000458C E868000000          <1> 	call	wdir
  2230                              <1> 		; jsr r0,wdir / free the directory entry
  2231 00004591 58                  <1> 	pop	eax ; 24/12/2021
  2232                              <1> 	;pop	ax
  2233                              <1> 		; mov (sp)+,r1 / get i-number back
  2234 00004592 E8350D0000          <1> 	call	iget
  2235                              <1> 		; jsr r0,iget / get i-node
  2236 00004597 E83C0E0000          <1> 	call	setimod
  2237                              <1> 		; jsr r0,setimod / set modified flag
  2238 0000459C FE0D[D86C0000]      <1> 	dec	byte [i.nlks]
  2239                              <1> 		; decb i.nlks / decrement the number of links
  2240                              <1> 	; 24/12/2021
  2241 000045A2 7505                <1> 	jnz	short sysunlink_2
  2242                              <1> 	;jnz	sysret
  2243                              <1> 		; bgt sysret9 / if this was not the last link
  2244                              <1> 			    ; / to file return
  2245                              <1> 	; AX = r1 = i-number
  2246 000045A4 E867090000          <1> 	call	anyi
  2247                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2248                              <1> 			 ; / Then free contents of file and destroy it.
  2249                              <1> sysunlink_2:
  2250 000045A9 E9F7F6FFFF          <1> 	jmp	sysret
  2251                              <1> 		; br sysret9
  2252                              <1> 
  2253                              <1> mkdir:
  2254                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2255                              <1> 	; 04/12/2015 (14 byte directory names)
  2256                              <1> 	; 12/10/2015
  2257                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2258                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2259                              <1> 	;
  2260                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2261                              <1> 	; by u.namep into the current directory.
  2262                              <1> 	;
  2263                              <1> 	; INPUTS ->
  2264                              <1> 	;    u.namep - points to a file name 
  2265                              <1> 	;	           that is about to be a directory entry.
  2266                              <1> 	;    ii - current directory's i-number.	
  2267                              <1> 	; OUTPUTS ->
  2268                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2269                              <1> 	;    u.off - points to entry to be filled 
  2270                              <1> 	;	     in the current directory		
  2271                              <1> 	;    u.base - points to start of u.dirbuf.
  2272                              <1> 	;    r1 - contains i-number of current directory 
  2273                              <1> 	;	
  2274                              <1> 	; ((AX = R1)) output
  2275                              <1> 	;
  2276                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2277                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2278                              <1> 	;
  2279                              <1> 
  2280                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2281 000045AE 31C0                <1> 	xor 	eax, eax
  2282 000045B0 BF[3C700000]        <1> 	mov     edi, u.dirbuf+2
  2283 000045B5 89FE                <1> 	mov	esi, edi
  2284 000045B7 AB                  <1> 	stosd
  2285 000045B8 AB                  <1> 	stosd
  2286                              <1> 	; 04/12/2015 (14 byte directory names)
  2287 000045B9 AB                  <1> 	stosd
  2288 000045BA 66AB                <1> 	stosw
  2289                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2290 000045BC 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2291                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2292                              <1> 	;mov 	ebp, [u.namep]
  2293 000045BE E871060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2294                              <1> 		; esi = physical address (page start + offset)
  2295                              <1> 		; ecx = byte count in the page (1 - 4096)
  2296                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2297                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2298                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2299                              <1> mkdir_1: ; 1: 
  2300 000045C3 45                  <1> 	inc	ebp ; 12/10/2015
  2301                              <1> 	;
  2302                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2303                              <1> 	 ; 01/08/2013
  2304 000045C4 AC                  <1> 	lodsb
  2305                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2306 000045C5 20C0                <1> 	and 	al, al
  2307 000045C7 7426                <1> 	jz 	short mkdir_3 	  
  2308                              <1> 		; beq 1f / if null, done
  2309 000045C9 3C2F                <1> 	cmp	al, '/'
  2310                              <1> 		; cmp r1,$'/ / is it a "/"?
  2311 000045CB 7413                <1> 	je	short mkdir_err
  2312                              <1> 	;je	error
  2313                              <1> 		; beq error9 / yes, error
  2314                              <1> 	; 12/10/2015
  2315                              <1> 	;dec	cx
  2316 000045CD 49                  <1> 	dec	ecx ; 24/12/2021
  2317 000045CE 7505                <1> 	jnz	short mkdir_2
  2318                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2319 000045D0 E865060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2320                              <1> 		; esi = physical address (page start + offset)
  2321                              <1> 		; ecx = byte count in the page
  2322                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2323                              <1> mkdir_2:
  2324 000045D5 81FF[4A700000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2325                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2326                              <1> 				     ; / a char?
  2327 000045DB 74E6                <1> 	je	short mkdir_1
  2328                              <1> 		; beq 1b / yes, go back
  2329 000045DD AA                  <1> 	stosb
  2330                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2331 000045DE EBE3                <1> 	jmp 	short mkdir_1
  2332                              <1> 		; br 1b / get next char
  2333                              <1> mkdir_err:
  2334                              <1> 	; 17/06/2015
  2335 000045E0 C705[5D700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2335 000045E8 0000                <1>
  2336 000045EA E996F6FFFF          <1> 	jmp	error
  2337                              <1> 
  2338                              <1> mkdir_3: ; 1:
  2339 000045EF A1[1C700000]        <1> 	mov	eax, [u.dirp]
  2340 000045F4 A3[24700000]        <1> 	mov	[u.off], eax
  2341                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2342                              <1> 				 ; / slot to u.off
  2343                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2344                              <1> 	; 29/04/2013
  2345 000045F9 C705[28700000]-     <1>         mov     dword [u.base], u.dirbuf
  2345 000045FF [3A700000]          <1>
  2346                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2347 00004603 C705[2C700000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2347 0000460B 0000                <1>
  2348                              <1> 		; mov $10.,u.count / u.count = 10
  2349 0000460D 66A1[EA6F0000]      <1> 	mov	ax, [ii] 
  2350                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2351 00004613 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2352 00004615 E8880D0000          <1> 	call 	access
  2353                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2354                              <1> 				 ; / for writing
  2355                              <1> 	; AX = i-number of current directory
  2356                              <1> 	; 01/08/2013
  2357 0000461A FE05[6F700000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2358                              <1> 	;call	writei
  2359                              <1> 	;	; jsr r0,writei / write into directory
  2360                              <1> 	;retn	
  2361                              <1> 	;	; rts r0
  2362                              <1> 	; 24/12/2021
  2363 00004620 E96E100000          <1> 	jmp	writei
  2364                              <1> 
  2365                              <1> sysexec:
  2366                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2367                              <1> 	; 23/10/2015
  2368                              <1> 	; 19/10/2015
  2369                              <1> 	; 18/10/2015
  2370                              <1> 	; 10/10/2015
  2371                              <1> 	; 26/08/2015
  2372                              <1> 	; 05/08/2015
  2373                              <1> 	; 29/07/2015
  2374                              <1> 	; 25/07/2015
  2375                              <1> 	; 24/07/2015
  2376                              <1> 	; 21/07/2015
  2377                              <1> 	; 20/07/2015
  2378                              <1> 	; 02/07/2015
  2379                              <1> 	; 01/07/2015
  2380                              <1> 	; 25/06/2015
  2381                              <1> 	; 24/06/2015
  2382                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2383                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2384                              <1> 	;
  2385                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2386                              <1> 	; pointed to by 'name' in the sysexec call. 
  2387                              <1> 	; 'sysexec' performs the following operations:
  2388                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2389                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2390                              <1> 	;    3. sets trap vectors to system routines.
  2391                              <1> 	;    4. loads arguments to be passed to executing file into
  2392                              <1> 	;	highest locations of user's core
  2393                              <1> 	;    5. puts pointers to arguments in locations immediately
  2394                              <1> 	;	following arguments.
  2395                              <1> 	;    6.	saves number of arguments in next location.
  2396                              <1> 	;    7. initializes user's stack area so that all registers
  2397                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2398                              <1> 	;	to core when 'sysret' restores registers 
  2399                              <1> 	;	and does an rti.
  2400                              <1> 	;    8. inializes u.r0 and u.sp
  2401                              <1> 	;    9. zeros user's core down to u.r0
  2402                              <1> 	;   10.	reads executable file from storage device into core
  2403                              <1> 	;	starting at location 'core'.
  2404                              <1> 	;   11.	sets u.break to point to end of user's code with
  2405                              <1> 	;	data area appended.
  2406                              <1> 	;   12.	calls 'sysret' which returns control at location
  2407                              <1> 	;	'core' via 'rti' instruction. 		  		
  2408                              <1> 	;
  2409                              <1> 	; Calling sequence:
  2410                              <1> 	;	sysexec; namep; argp
  2411                              <1> 	; Arguments:
  2412                              <1> 	;	namep - points to pathname of file to be executed
  2413                              <1> 	;	argp  - address of table of argument pointers
  2414                              <1> 	;	argp1... argpn - table of argument pointers
  2415                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2416                              <1> 	; Inputs: (arguments)
  2417                              <1> 	; Outputs: -	
  2418                              <1> 	; ...............................................................
  2419                              <1> 	;
  2420                              <1> 	; Retro UNIX 386 v1 modification: 
  2421                              <1> 	;	User application runs in it's own virtual space 
  2422                              <1> 	;	which is izolated from kernel memory (and other
  2423                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2424                              <1> 	;	privilige mode. Virtual start address is always 0.
  2425                              <1> 	;	User's core memory starts at linear address 400000h
  2426                              <1> 	;	(the end of the 1st 4MB).
  2427                              <1> 	;
  2428                              <1> 	; Retro UNIX 8086 v1 modification: 
  2429                              <1> 	;	user/application segment and system/kernel segment
  2430                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2431                              <1> 	;	are different (user's registers are saved to 
  2432                              <1> 	;	and then restored from system's stack.)
  2433                              <1> 	;
  2434                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2435                              <1> 	;	      arguments which were in these registers;
  2436                              <1> 	;	      but, it returns by putting the 1st argument
  2437                              <1> 	;	      in 'u.namep' and the 2nd argument
  2438                              <1> 	;	      on top of stack. (1st argument is offset of the
  2439                              <1> 	;	      file/path name in the user's program segment.)		 	
  2440                              <1> 	
  2441                              <1> 	;call	arg2
  2442                              <1> 	; * name - 'u.namep' points to address of file/path name
  2443                              <1> 	;          in the user's program segment ('u.segmnt')
  2444                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2445                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2446                              <1> 	;          which is on top of stack.
  2447                              <1> 	;
  2448                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2449                              <1> 
  2450                              <1> 	; 23/06/2015 (32 bit modifications)
  2451                              <1> 
  2452 00004625 891D[20700000]      <1> 	mov	[u.namep], ebx ; argument 1
  2453                              <1>         ; 18/10/2015
  2454 0000462B 890D[88700000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2455 00004631 E8C1040000          <1> 	call	namei
  2456                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2457                              <1> 			     ; / named in sysexec call in r1
  2458                              <1> 	;jc	error
  2459                              <1> 		; br error9
  2460 00004636 731E                <1> 	jnc	short sysexec_0
  2461                              <1> 	;
  2462                              <1> 	; 'file not found !' error
  2463 00004638 C705[5D700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2463 00004640 0000                <1>
  2464 00004642 E93EF6FFFF          <1> 	jmp	error 
  2465                              <1> sysexec_not_exf:
  2466                              <1> 	; 'not executable file !' error
  2467 00004647 C705[5D700000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2467 0000464F 0000                <1>
  2468 00004651 E92FF6FFFF          <1> 	jmp	error 
  2469                              <1> sysexec_0:
  2470 00004656 E8710C0000          <1> 	call	iget
  2471                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2472                              <1> 	; 24/12/2021
  2473 0000465B F605[D66C0000]10    <1> 	test	byte [i.flgs], 10h
  2474                              <1> 	;test	word [i.flgs], 10h
  2475                              <1> 	;	; bit $20,i.flgs / is file executable
  2476 00004662 74E3                <1> 	jz	short sysexec_not_exf
  2477                              <1> 	;jz	error
  2478                              <1> 		; beq error9
  2479                              <1> 	;;
  2480 00004664 E8CE130000          <1> 	call	iopen
  2481                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2482                              <1> 			     ; / given in r1 (opens file)
  2483                              <1> 	; AX = i-number of the file
  2484                              <1> 	; 24/12/2021
  2485 00004669 F605[D66C0000]20    <1> 	test	byte [i.flgs], 20h
  2486                              <1> 	;test	word [i.flgs], 20h
  2487                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2488 00004670 7415                <1> 	jz	short sysexec_1
  2489                              <1> 		; beq 1f
  2490 00004672 803D[54700000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2491                              <1> 		; tstb u.uid / test user id
  2492 00004679 760C                <1> 	jna	short sysexec_1
  2493                              <1> 		; beq 1f / super user
  2494 0000467B 8A0D[D96C0000]      <1> 	mov	cl, [i.uid]
  2495 00004681 880D[54700000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2496                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2497                              <1> 				 ; / as process user id
  2498                              <1> sysexec_1:
  2499                              <1> 	; 24/12/2021
  2500                              <1> 	; 18/10/2215
  2501                              <1> 	; 10/10/2015
  2502                              <1> 	; 24/07/2015
  2503                              <1> 	; 21/07/2015
  2504                              <1> 	; 25/06/2015
  2505                              <1> 	; 24/06/2015
  2506                              <1>         ; Moving arguments to the end of [u.upage]
  2507                              <1> 	; (by regarding page borders in user's memory space)
  2508                              <1> 	;
  2509                              <1> 	; 10/10/2015
  2510                              <1> 	; 21/07/2015
  2511 00004687 89E5                <1> 	mov	ebp, esp ; (**)
  2512                              <1> 	; 18/10/2015
  2513 00004689 89EF                <1> 	mov 	edi, ebp
  2514 0000468B B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2515                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2516 00004690 29CF                <1> 	sub	edi, ecx
  2517 00004692 89FC                <1> 	mov	esp, edi
  2518 00004694 31C0                <1> 	xor	eax, eax
  2519 00004696 A3[30700000]        <1> 	mov 	[u.nread], eax ; 0
  2520 0000469B 49                  <1> 	dec	ecx ; 256 - 1
  2521 0000469C 890D[2C700000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2522                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2523                              <1> sysexec_2:
  2524 000046A2 8B35[88700000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2525 000046A8 E86B020000          <1> 	call	get_argp
  2526 000046AD B904000000          <1> 	mov	ecx, 4 ; mov ecx, 4
  2527                              <1> sysexec_3:
  2528 000046B2 21C0                <1> 	and	eax, eax
  2529 000046B4 7456                <1> 	jz	short sysexec_6
  2530                              <1> 	; 18/10/2015
  2531 000046B6 010D[88700000]      <1> 	add	[argv], ecx ; 4
  2532 000046BC 66FF05[86700000]    <1> 	inc	word [argc]
  2533                              <1> 	;
  2534 000046C3 A3[28700000]        <1> 	mov	[u.base], eax
  2535                              <1>  	; 23/10/2015
  2536 000046C8 66C705[6D700000]00- <1> 	mov	word [u.pcount], 0
  2536 000046D0 00                  <1>
  2537                              <1> sysexec_4:
  2538 000046D1 E873110000          <1> 	call	cpass ; get a character from user's core memory
  2539 000046D6 750B                <1>         jnz	short sysexec_5
  2540                              <1> 		; (max. 255 chars + null)
  2541                              <1> 	; 18/10/2015
  2542 000046D8 28C0                <1> 	sub 	al, al
  2543 000046DA AA                  <1> 	stosb
  2544 000046DB FF05[30700000]      <1> 	inc	dword [u.nread]
  2545 000046E1 EB29                <1> 	jmp	short sysexec_6
  2546                              <1> sysexec_5:
  2547 000046E3 AA                  <1> 	stosb
  2548 000046E4 20C0                <1> 	and 	al, al
  2549 000046E6 75E9                <1> 	jnz	short sysexec_4
  2550                              <1> 	;mov	ecx, 4
  2551                              <1> 	; 24/12/2021
  2552 000046E8 29C9                <1> 	sub	ecx, ecx
  2553 000046EA B104                <1> 	mov	cl, 4
  2554                              <1> 	;cmp	[ncount], ecx ; 4
  2555                              <1> 	; 24/12/2021
  2556 000046EC 66390D[84700000]    <1> 	cmp	[ncount], cx ; 4
  2557 000046F3 72AD                <1> 	jb	short sysexec_2
  2558 000046F5 8B35[80700000]      <1> 	mov	esi, [nbase]
  2559 000046FB 010D[80700000]      <1> 	add	[nbase], ecx ; 4	
  2560 00004701 66290D[84700000]    <1> 	sub	[ncount], cx 
  2561 00004708 8B06                <1> 	mov	eax, [esi]
  2562 0000470A EBA6                <1> 	jmp	short sysexec_3
  2563                              <1> sysexec_6:
  2564                              <1> 	; 18/10/2015
  2565                              <1> 	; argument list transfer from user's core memory to
  2566                              <1> 	; kernel stack frame is OK here.
  2567                              <1> 	; [u.nread] = ; argument list length
  2568                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2569                              <1> 	;
  2570                              <1> 	; 18/10/2015
  2571                              <1> 	; 24/07/2015
  2572                              <1>         ; 21/07/2015
  2573                              <1> 	; 02/07/2015
  2574                              <1> 	; 25/06/2015
  2575                              <1> 	; 24/06/2015
  2576                              <1> 	; 23/06/2015
  2577                              <1> 	;
  2578 0000470C 8B1D[65700000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2579 00004712 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2580 00004714 740A                <1> 	jz	short sysexec_7
  2581 00004716 A1[61700000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2582 0000471B E84AE9FFFF          <1> 	call	deallocate_page_dir
  2583                              <1> sysexec_7:
  2584 00004720 E87AE8FFFF          <1> 	call	make_page_dir
  2585                              <1> 	;jc	short sysexec_14
  2586 00004725 0F82F2EDFFFF        <1> 	jc	panic  ; allocation error 
  2587                              <1> 		       ; after a deallocation would be nonsence !?
  2588                              <1> 	; 24/07/2015
  2589                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2590                              <1> 	;     of the user's page directory
  2591                              <1> 	;     (It is needed for interrupts!)
  2592                              <1> 	; 18/10/2015
  2593 0000472B 8B15[286C0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2594 00004731 8B02                <1> 	mov	eax, [edx] ; physical address of
  2595                              <1> 			   ; kernel's first page table (1st 4 MB)
  2596                              <1> 			   ; (PDE 0 of kernel's page directory)
  2597 00004733 8B15[61700000]      <1> 	mov 	edx, [u.pgdir]
  2598 00004739 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2599                              <1> 	;
  2600                              <1> 	; 20/07/2015
  2601 0000473B BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2602                              <1> 	; 18/10/2015
  2603 00004740 BE[78700000]        <1> 	mov	esi, pcore ; physical start address
  2604                              <1> sysexec_8:	
  2605 00004745 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2606 0000474A E86EE8FFFF          <1> 	call	make_page_table
  2607                              <1> 	;jc	panic
  2608                              <1> 	; 24/12/2021
  2609 0000474F 721D                <1> 	jc	short sysexec_panic
  2610                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2611 00004751 E875E8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2612                              <1> 	;jc	panic
  2613                              <1> 	; 24/12/2021
  2614 00004756 7216                <1> 	jc	short sysexec_panic
  2615                              <1> 	;
  2616 00004758 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2617                              <1> 	; ebx = virtual address (24/07/2015)
  2618                              <1> 	; 24/12/2021
  2619                              <1> 	;call 	add_to_swap_queue
  2620                              <1> 	; 18/10/2015
  2621                              <1> 	; 18/10/2015
  2622 0000475A 81FE[7C700000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2623 00004760 7411                <1> 	je	short sysexec_9 ; yes
  2624 00004762 BE[7C700000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2625                              <1> 	; 20/07/2015
  2626 00004767 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2627                              <1> 	; ebx = virtual end address + segment base address - 4K
  2628 0000476C EBD7                <1>         jmp     short sysexec_8
  2629                              <1> 
  2630                              <1> sysexec_panic:
  2631                              <1> 	; 26/03/2021
  2632 0000476E E9AAEDFFFF          <1> 	jmp	panic
  2633                              <1> 
  2634                              <1> sysexec_9:
  2635                              <1> 	; 18/10/2015
  2636                              <1> 	; 26/08/2015
  2637                              <1> 	; 25/06/2015
  2638                              <1> 	; move arguments from kernel stack to [ecore]
  2639                              <1> 	; (argument list/line will be copied from kernel stack
  2640                              <1> 	; frame to the last (stack) page of user's core memory)
  2641                              <1> 	; 18/10/2015
  2642 00004773 8B3D[7C700000]      <1> 	mov	edi, [ecore]
  2643 00004779 81C700100000        <1> 	add	edi, PAGE_SIZE
  2644 0000477F 0FB705[86700000]    <1> 	movzx	eax, word [argc]
  2645 00004786 09C0                <1> 	or	eax, eax
  2646 00004788 7509                <1> 	jnz	short sysexec_10
  2647 0000478A 89FB                <1> 	mov 	ebx, edi
  2648 0000478C 83EB04              <1> 	sub	ebx, 4 
  2649 0000478F 8903                <1> 	mov	[ebx], eax ; 0
  2650 00004791 EB40                <1> 	jmp 	short sysexec_13
  2651                              <1> sysexec_10:
  2652 00004793 8B0D[30700000]      <1> 	mov	ecx, [u.nread]
  2653                              <1> 	;mov 	esi, [argv}
  2654 00004799 89E6                <1> 	mov	esi, esp ; start address of argument list
  2655 0000479B 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2656 0000479D 89C2                <1> 	mov	edx, eax
  2657 0000479F FEC2                <1> 	inc	dl ; argument count + 1 for argc value  
  2658 000047A1 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2659 000047A4 89FB                <1> 	mov	ebx, edi
  2660 000047A6 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2661 000047A9 29D3                <1> 	sub 	ebx, edx
  2662 000047AB 89FA                <1> 	mov	edx, edi
  2663 000047AD F3A4                <1> 	rep	movsb
  2664 000047AF 89D6                <1> 	mov 	esi, edx
  2665 000047B1 89DF                <1> 	mov 	edi, ebx
  2666 000047B3 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2667 000047B8 2B15[7C700000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2668 000047BE AB                  <1> 	stosd	; eax = argument count	
  2669                              <1> sysexec_11:
  2670 000047BF 89F0                <1> 	mov	eax, esi
  2671 000047C1 01D0                <1> 	add	eax, edx
  2672 000047C3 AB                  <1> 	stosd  ; eax = virtual address
  2673 000047C4 FE0D[86700000]      <1> 	dec	byte [argc]
  2674 000047CA 7407                <1> 	jz	short sysexec_13
  2675                              <1> sysexec_12:
  2676 000047CC AC                  <1> 	lodsb
  2677 000047CD 20C0                <1> 	and	al, al
  2678 000047CF 75FB                <1> 	jnz	short sysexec_12
  2679 000047D1 EBEC                <1> 	jmp	short sysexec_11
  2680                              <1> 	;
  2681                              <1> 	; 1:
  2682                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2683                              <1> 			     ; / pointers to arguments to be passed
  2684                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2685                              <1> 			      ; / u.quit = 1 take quit
  2686                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2687                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2688                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2689                              <1> 			       ; / system routine
  2690                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2691                              <1> 			       ; / set to take system routine
  2692                              <1> 		; mov $sstack,sp / stack space used during swapping
  2693                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2694                              <1> 		; mov $ecore,r5 / r5 has end of core
  2695                              <1> 		; mov $core,r4 / r4 has start of users core
  2696                              <1> 		; mov r4,u.base / u.base has start of users core
  2697                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2698                              <1> 	; 1:
  2699                              <1> 		; tst (r2)+ / argument char = "nul"
  2700                              <1> 		; bne 1b
  2701                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2702                              <1> 			  ; / end of argument pointer list
  2703                              <1> 	; 1:
  2704                              <1> 	     ; / move arguments to bottom of users core
  2705                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2706                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2707                              <1> 			    ; / ptr list
  2708                              <1> 		; blo 1f / branch to 1f when all arguments
  2709                              <1> 		       ; / are moved
  2710                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2711                              <1> 	; 2:
  2712                              <1> 		; tstb (r3)+
  2713                              <1> 		; bne 2b / scan argument for \0 (nul)
  2714                              <1> 
  2715                              <1> 	; 2:
  2716                              <1> 		; movb -(r3),-(r5) / move argument char 
  2717                              <1> 				 ; / by char starting at "ecore"
  2718                              <1> 		; cmp r3,(r2) / moved all characters in 
  2719                              <1> 			    ; / this argument
  2720                              <1> 		; bhi 2b / branch 2b if not
  2721                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2722                              <1> 			     ; / r5 has pointer to nth arg
  2723                              <1> 		; br 1b / string
  2724                              <1> 	; 1:
  2725                              <1> 		; clrb -(r5)
  2726                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2727                              <1> 			; / last word of argument strings
  2728                              <1> 		; mov $core,r2
  2729                              <1> 	
  2730                              <1> 	; 1: / move argument pointers into core following 
  2731                              <1> 	      ; / argument strings
  2732                              <1> 		; cmp r2,r4
  2733                              <1> 		; bhis 1f / branch to 1f when all pointers
  2734                              <1> 			; / are moved
  2735                              <1> 		; mov (r2)+,-(r5)
  2736                              <1> 		; br 1b
  2737                              <1> 	; 1:
  2738                              <1> 		; sub $core,r4 / gives number of arguments *2
  2739                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2740                              <1> 		       ; / the number of args stored
  2741                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2742                              <1> 			     ; / of the argument pointers
  2743                              <1> sysexec_13:
  2744                              <1> 	; 19/10/2015
  2745                              <1> 	; 18/10/2015
  2746                              <1> 	; 29/07/2015
  2747                              <1> 	; 25/07/2015
  2748                              <1> 	; 24/07/2015
  2749                              <1> 	; 20/07/2015
  2750                              <1> 	; 25/06/2015
  2751                              <1> 	; 24/06/2015
  2752                              <1> 	; 23/06/2015
  2753                              <1> 	;
  2754                              <1> 	; moving arguments to [ecore] is OK here..
  2755                              <1> 	; 18/10/2015
  2756 000047D3 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2757                              <1> 	; ebx = beginning addres of argument list pointers
  2758                              <1> 	;	in user's stack
  2759                              <1> 	; 19/10/2015
  2760 000047D5 2B1D[7C700000]      <1> 	sub 	ebx, [ecore]
  2761 000047DB 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2762                              <1> 			; end of core - 4096 (last page)
  2763                              <1> 			; (virtual address)
  2764 000047E1 891D[88700000]      <1> 	mov	[argv], ebx
  2765 000047E7 891D[34700000]      <1> 	mov	[u.break], ebx ; available user memory
  2766                              <1> 	;
  2767 000047ED 29C0                <1> 	sub	eax, eax
  2768 000047EF C705[2C700000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2768 000047F7 0000                <1>
  2769                              <1> 		; mov $14,u.count
  2770 000047F9 C705[18700000]-     <1> 	mov	dword [u.fofp], u.off
  2770 000047FF [24700000]          <1>
  2771                              <1> 		; mov $u.off,u.fofp
  2772 00004803 A3[24700000]        <1> 	mov	[u.off], eax ; 0
  2773                              <1> 		; clr u.off / set offset in file to be read to zero
  2774                              <1> 	; 25/07/2015
  2775 00004808 A3[28700000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2776                              <1> 	; 25/06/2015 
  2777 0000480D 66A1[EA6F0000]      <1> 	mov	ax, [ii]
  2778                              <1> 	; AX = i-number of the executable file
  2779 00004813 E88B0C0000          <1> 	call	readi
  2780                              <1> 		; jsr r0,readi / read in first six words of 
  2781                              <1> 			; / user's file, starting at $core
  2782                              <1> 		; mov sp,r5 / put users stack address in r5
  2783                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2784                              <1> 				; / from r5 (leaves number of words
  2785                              <1> 				; / less 26 available for
  2786                              <1> 			     	; / program in user core
  2787                              <1> 		; mov r5,u.count /
  2788                              <1> 	; 25/06/2015
  2789 00004818 8B0D[34700000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2790 0000481E 890D[2C700000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2791                              <1> 	;
  2792 00004824 8B0D[30700000]      <1> 	mov	ecx, [u.nread]
  2793 0000482A 890D[34700000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2794 00004830 80F920              <1> 	cmp	cl, 32
  2795 00004833 7540                <1>         jne     short sysexec_15
  2796                              <1> 	;:
  2797                              <1> 	; 25/06/2015
  2798                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2799                              <1> 	; 18/10/2015
  2800 00004835 8B35[78700000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2801                              <1> 		             ; (phys. start addr. of the exec. file)
  2802 0000483B AD                  <1> 	lodsd
  2803 0000483C 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2804 00004840 7533                <1> 	jne	short sysexec_15
  2805                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2806                              <1> 			      ; / if file is standard a.out format
  2807                              <1> 		; bne 1f / branch, if not standard format
  2808 00004842 AD                  <1> 	lodsd
  2809 00004843 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2810 00004845 AD                  <1> 	lodsd
  2811 00004846 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2812                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2813                              <1> 		              ; / number of bytes in program text	
  2814                              <1> 		; sub $14,r5 / subtract 12
  2815 00004848 89CB                <1> 	mov	ebx, ecx
  2816                              <1> 	;
  2817                              <1> 	; 25/06/2015
  2818                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2819                              <1> 	;	and SINGLIX operating systems (as code template).
  2820                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2821                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2822                              <1> 	;	Overrun is not possible for current version. 	
  2823                              <1> 	;
  2824 0000484A AD                  <1> 	lodsd	
  2825 0000484B 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2826 0000484D 3B1D[2C700000]      <1> 	cmp	ebx, [u.count]
  2827 00004853 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2828                              <1> 	;
  2829                              <1> 	; 24/07/2015
  2830                              <1> 	; add bss section size to [u.break]
  2831 00004855 0105[34700000]      <1> 	add 	[u.break], eax
  2832                              <1> 	;
  2833 0000485B 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2834                              <1> 	;cmp	ecx, [u.count]
  2835                              <1> 	;jnb	short sysexec_16
  2836                              <1> 		; cmp r5,u.count /
  2837                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2838 0000485E 890D[2C700000]      <1> 	mov	[u.count], ecx ; required read count
  2839                              <1> 		; mov r5,u.count
  2840                              <1> 	;
  2841 00004864 EB2A                <1> 	jmp	short sysexec_16
  2842                              <1> 	;
  2843                              <1> sysexec_14:
  2844                              <1> 	; 23/06/2015
  2845                              <1> 	; insufficient (out of) memory
  2846 00004866 C705[5D700000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2846 0000486E 0000                <1>
  2847 00004870 E910F4FFFF          <1> 	jmp	error
  2848                              <1> 	;
  2849                              <1> sysexec_15:
  2850                              <1> 	; 25/06/2015
  2851 00004875 0FB715[DA6C0000]    <1>         movzx   edx, word [i.size] ; file size
  2852 0000487C 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2853 0000487E 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2854 00004880 01D1                <1> 	add	ecx, edx ; [i.size]
  2855 00004882 3B0D[2C700000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2856 00004888 77DC                <1> 	ja	short sysexec_14
  2857 0000488A 8915[2C700000]      <1> 	mov	[u.count], edx
  2858                              <1> sysexec_16:
  2859 00004890 66A1[EA6F0000]      <1> 	mov	ax, [ii] ; i-number
  2860 00004896 E8080C0000          <1> 	call	readi
  2861                              <1> 		; add core+10,u.nread / add size of user data area 
  2862                              <1> 		                    ; / to u.nread
  2863                              <1> 		; br 2f
  2864                              <1> 	; 1:
  2865                              <1> 		; jsr r0,readi / read in rest of file
  2866                              <1> 	; 2:
  2867 0000489B 8B0D[30700000]      <1> 	mov	ecx, [u.nread]
  2868 000048A1 010D[34700000]      <1> 	add	[u.break], ecx
  2869                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2870                              <1> 				    ; / user code
  2871                              <1> 		; add $core+14,u.break / plus data area
  2872                              <1> sysexec_17: ; 20/07/2015
  2873                              <1> 	;mov	ax, [ii] ; i-number
  2874 000048A7 E8B8120000          <1> 	call	iclose
  2875                              <1> 		; jsr r0,iclose / does nothing
  2876 000048AC 31C0                <1>         xor     eax, eax
  2877 000048AE FEC0                <1> 	inc	al
  2878 000048B0 66A3[4C700000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2879 000048B6 66A3[4E700000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2880                              <1> 	; 02/07/2015
  2881 000048BC 833D[65700000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2882 000048C3 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2883                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2884 000048C5 8B15[286C0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2885 000048CB 8915[65700000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2886                              <1> sysexec_18:
  2887                              <1> 	; 18/10/2015
  2888                              <1> 	; 05/08/2015
  2889                              <1> 	; 29/07/2015
  2890 000048D1 8B2D[88700000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2891                              <1> 			    ; list pointers (argument count)
  2892 000048D7 FA                  <1> 	cli
  2893 000048D8 8B25[C46B0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2894                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2895                              <1> 			    ; for this process	 
  2896                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2897                              <1> 	;xor	eax, eax ; 0
  2898 000048DE FEC8                <1> 	dec	al ; eax = 0
  2899 000048E0 66BA2300            <1> 	mov	dx, UDATA
  2900 000048E4 6652                <1> 	push	dx  ; user's stack segment
  2901 000048E6 55                  <1> 	push	ebp ; user's stack pointer
  2902                              <1> 		    ; (points to number of arguments)
  2903 000048E7 FB                  <1> 	sti
  2904 000048E8 9C                  <1> 	pushfd	; EFLAGS
  2905                              <1> 		; Set IF for enabling interrupts in user mode	
  2906                              <1> 	;or	dword [esp], 200h 
  2907                              <1> 	;
  2908                              <1> 	;mov	bx, UCODE
  2909                              <1> 	;push	bx ; user's code segment
  2910 000048E9 6A1B                <1> 	push	UCODE
  2911                              <1> 	;push	0
  2912 000048EB 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2913                              <1> 		; clr -(r5) / popped into ps when rti in 
  2914                              <1> 			  ; / sysrele is executed
  2915                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2916                              <1> 		                ; / in sysrele is executed
  2917                              <1> 		;mov r5,0f / load second copyz argument
  2918                              <1> 		;tst -(r5) / decrement r5
  2919 000048EC 8925[00700000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2920                              <1> 	; 05/08/2015
  2921                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2922                              <1> 	; ('push dx' would cause to general protection fault, 
  2923                              <1> 	; after 'pop ds' etc.)
  2924                              <1> 	;
  2925                              <1> 	;; push dx ; ds (UDATA)
  2926                              <1> 	;; push dx ; es (UDATA)
  2927                              <1> 	;; push dx ; fs (UDATA)
  2928                              <1> 	;; push dx ; gs (UDATA)
  2929                              <1> 	;
  2930                              <1> 	; This is a trick to prevent general protection fault
  2931                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  2932 000048F2 8EC2                <1> 	mov 	es, dx ; UDATA
  2933 000048F4 06                  <1> 	push 	es ; ds (UDATA)
  2934 000048F5 06                  <1> 	push 	es ; es (UDATA)
  2935 000048F6 06                  <1> 	push 	es ; fs (UDATA)
  2936 000048F7 06                  <1> 	push	es ; gs (UDATA)
  2937 000048F8 66BA1000            <1> 	mov	dx, KDATA
  2938 000048FC 8EC2                <1> 	mov	es, dx
  2939                              <1> 	;
  2940                              <1> 	;; pushad simulation
  2941 000048FE 89E5                <1> 	mov	ebp, esp ; esp before pushad
  2942 00004900 50                  <1> 	push	eax ; eax (0)
  2943 00004901 50                  <1> 	push	eax ; ecx (0)
  2944 00004902 50                  <1> 	push	eax ; edx (0)
  2945 00004903 50                  <1> 	push	eax ; ebx (0)
  2946 00004904 55                  <1> 	push	ebp ; esp before pushad
  2947 00004905 50                  <1> 	push	eax ; ebp (0)
  2948 00004906 50                  <1> 	push	eax ; esi (0)		
  2949 00004907 50                  <1> 	push	eax ; edi (0)	
  2950                              <1> 	;
  2951 00004908 A3[08700000]        <1> 	mov	[u.r0], eax ; eax = 0
  2952 0000490D 8925[04700000]      <1> 	mov	[u.usp], esp
  2953                              <1> 		; mov r5,u.r0 /
  2954                              <1> 		; sub $16.,r5 / skip 8 words
  2955                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  2956                              <1> 		;             / effectively zeroes all regs
  2957                              <1> 			    ; / when sysrele is executed
  2958                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  2959                              <1> 		; clr u.break
  2960                              <1> 		; mov r5,sp / point sp to user's stack
  2961                              <1> 	;
  2962 00004913 E98FF3FFFF          <1> 	jmp	sysret0
  2963                              <1> 	;jmp	sysret
  2964                              <1> 		; br sysret3 / return to core image at $core
  2965                              <1> 
  2966                              <1> get_argp:
  2967                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2968                              <1> 	; 18/10/2015 (nbase, ncount)
  2969                              <1> 	; 21/07/2015
  2970                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  2971                              <1> 	; Get (virtual) address of argument from user's core memory
  2972                              <1> 	;
  2973                              <1> 	; INPUT:
  2974                              <1> 	;	esi = virtual address of argument pointer
  2975                              <1> 	; OUTPUT:
  2976                              <1> 	;	eax = virtual address of argument
  2977                              <1> 	;
  2978                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  2979                              <1> 	;
  2980 00004918 833D[65700000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  2981                              <1> 				    ; (the caller is kernel)
  2982                              <1> 	;jna	short get_argpk 
  2983                              <1> 	; 24/12/2021
  2984 0000491F 7719                <1> 	ja	short get_argp5
  2985                              <1> get_argpk:
  2986                              <1> 	; Argument is in kernel's memory space
  2987 00004921 66C705[84700000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  2987 00004929 10                  <1>
  2988 0000492A 8935[80700000]      <1> 	mov	[nbase], esi
  2989 00004930 8305[80700000]04    <1> 	add	dword [nbase], 4
  2990 00004937 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  2991 00004939 C3                  <1> 	retn
  2992                              <1> get_argp5:
  2993 0000493A 89F3                <1>      	mov	ebx, esi
  2994 0000493C E8E5E9FFFF          <1> 	call	get_physical_addr ; get physical address
  2995 00004941 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  2996 00004943 A3[80700000]        <1> 	mov 	[nbase], eax ; physical address	
  2997 00004948 66890D[84700000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  2998 0000494F B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  2999                              <1> 	;cmp	cx, ax ; 4
  3000 00004954 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3001 00004956 734C                <1> 	jnb	short get_argp2
  3002 00004958 89F3                <1> 	mov	ebx, esi
  3003 0000495A 01CB                <1> 	add	ebx, ecx
  3004 0000495C E8C5E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3005 00004961 7237                <1> 	jc	short get_argp_err
  3006                              <1> 	;push	esi
  3007 00004963 89C6                <1> 	mov	esi, eax
  3008 00004965 66870D[84700000]    <1> 	xchg	cx, [ncount]
  3009 0000496C 8735[80700000]      <1> 	xchg	esi, [nbase]
  3010 00004972 B504                <1> 	mov	ch, 4
  3011 00004974 28CD                <1> 	sub	ch, cl
  3012                              <1> get_argp0:
  3013 00004976 AC                  <1> 	lodsb
  3014                              <1> 	;push	ax
  3015                              <1> 	; 24/12/2021
  3016 00004977 50                  <1> 	push	eax
  3017 00004978 FEC9                <1> 	dec	cl
  3018 0000497A 75FA                <1>         jnz     short get_argp0
  3019 0000497C 8B35[80700000]      <1> 	mov	esi, [nbase]
  3020                              <1> 	; 21/07/2015
  3021 00004982 0FB6C5              <1> 	movzx	eax, ch
  3022 00004985 0105[80700000]      <1> 	add	[nbase], eax
  3023 0000498B 662905[84700000]    <1> 	sub	[ncount], ax
  3024                              <1> get_argp1:
  3025 00004992 AC                  <1> 	lodsb
  3026 00004993 FECD                <1> 	dec	ch
  3027 00004995 7423                <1>         jz      short get_argp3
  3028                              <1> 	;push	ax
  3029                              <1> 	; 24/12/2021
  3030 00004997 50                  <1> 	push	eax
  3031 00004998 EBF8                <1> 	jmp     short get_argp1
  3032                              <1> 	; 24/12/2021
  3033                              <1> get_argp_err:
  3034 0000499A A3[5D700000]        <1> 	mov	[u.error], eax
  3035 0000499F E9E1F2FFFF          <1> 	jmp	error
  3036                              <1> get_argp2:
  3037                              <1> 	; 21/07/2015
  3038                              <1> 	;mov	eax, 4
  3039 000049A4 8B15[80700000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3040 000049AA 0105[80700000]      <1> 	add	[nbase], eax
  3041 000049B0 662905[84700000]    <1> 	sub	[ncount], ax
  3042                              <1> 	;
  3043 000049B7 8B02                <1> 	mov	eax, [edx]
  3044 000049B9 C3                  <1> 	retn
  3045                              <1> get_argp3:
  3046 000049BA B103                <1> 	mov	cl, 3
  3047                              <1> get_argp4:
  3048 000049BC C1E008              <1> 	shl	eax, 8
  3049                              <1> 	;pop	dx
  3050                              <1> 	; 24/12/2021
  3051 000049BF 5A                  <1> 	pop	edx
  3052 000049C0 88D0                <1> 	mov 	al, dl
  3053 000049C2 E2F8                <1>         loop    get_argp4
  3054                              <1> 	;pop	esi
  3055 000049C4 C3                  <1> 	retn	
  3056                              <1> 
  3057                              <1> sysfstat: 
  3058                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3059                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3060                              <1> 	;
  3061                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3062                              <1> 	; on open files instead of files given by name. It puts the
  3063                              <1> 	; buffer address on the stack, gets the i-number and
  3064                              <1> 	; checks to see if the file is open for reading or writing.
  3065                              <1> 	; If the file is open for writing (i-number is negative)
  3066                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3067                              <1> 	; is made.	
  3068                              <1> 	;
  3069                              <1> 	; Calling sequence:
  3070                              <1> 	;	sysfstat; buf
  3071                              <1> 	; Arguments:
  3072                              <1> 	;	buf - buffer address
  3073                              <1> 	;
  3074                              <1> 	; Inputs: *u.r0 - file descriptor
  3075                              <1> 	; Outputs: buffer is loaded with file information
  3076                              <1> 	; ...............................................................
  3077                              <1> 	;				
  3078                              <1> 	; Retro UNIX 8086 v1 modification:
  3079                              <1> 	;       'sysfstat' system call has two arguments; so,
  3080                              <1> 	;	* 1st argument, file descriptor is in BX register
  3081                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3082                              <1> 
  3083                              <1> 	; / set status of open file
  3084                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3085 000049C5 51                  <1> 	push	ecx
  3086                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3087                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3088                              <1> 		; jsr r0,getf / get the files i-number
  3089                              <1> 	; BX = file descriptor (file number)
  3090 000049C6 E8F5000000          <1> 	call	getf1
  3091 000049CB 6621C0              <1> 	and	ax, ax ; i-number of the file
  3092                              <1> 		; tst	r1 / is it 0?
  3093                              <1> 	;jz	error
  3094                              <1> 		; beq error3 / yes, error
  3095 000049CE 750F                <1> 	jnz	short sysfstat1
  3096 000049D0 C705[5D700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3096 000049D8 0000                <1>
  3097 000049DA E9A6F2FFFF          <1> 	jmp	error
  3098                              <1> sysfstat1:
  3099 000049DF 80FC80              <1> 	cmp	ah, 80h
  3100 000049E2 7223                <1>         jb      short sysstat1
  3101                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3102 000049E4 66F7D8              <1> 	neg	ax
  3103                              <1> 		; neg r1 / make it positive, then branch
  3104 000049E7 EB1E                <1> 	jmp	short sysstat1
  3105                              <1> 		; br 1f / to 1f
  3106                              <1> sysstat:
  3107                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3108                              <1> 	; 18/10/2015
  3109                              <1> 	; 07/10/2015
  3110                              <1> 	; 02/09/2015
  3111                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3112                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3113                              <1> 	;
  3114                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3115                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3116                              <1> 	; long and information about the file placed in it.	
  3117                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3118                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3119                              <1> 	; is then loaded and the results are given in the UNIX
  3120                              <1> 	; Programmers Manual sysstat (II).	
  3121                              <1> 	;
  3122                              <1> 	; Calling sequence:
  3123                              <1> 	;	sysstat; name; buf
  3124                              <1> 	; Arguments:
  3125                              <1> 	;	name - points to the name of the file
  3126                              <1> 	;	buf - address of a 34 bytes buffer
  3127                              <1> 	; Inputs: -
  3128                              <1> 	; Outputs: buffer is loaded with file information
  3129                              <1> 	; ...............................................................
  3130                              <1> 	;				
  3131                              <1> 	; Retro UNIX 8086 v1 modification: 
  3132                              <1> 	;       'sysstat' system call has two arguments; so,
  3133                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3134                              <1> 	;	to get sysstat system call arguments from the user;
  3135                              <1> 	;	* 1st argument, name is pointed to by BX register
  3136                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3137                              <1> 	;
  3138                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3139                              <1> 	;	      arguments which were in these registers;
  3140                              <1> 	;	      but, it returns by putting the 1st argument
  3141                              <1> 	;	      in 'u.namep' and the 2nd argument
  3142                              <1> 	;	      on top of stack. (1st argument is offset of the
  3143                              <1> 	;	      file/path name in the user's program segment.)		 	
  3144                              <1> 	
  3145                              <1> 	; / ; name of file; buffer - get files status
  3146                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3147 000049E9 891D[20700000]      <1> 	mov	[u.namep], ebx
  3148 000049EF 51                  <1> 	push	ecx
  3149 000049F0 E802010000          <1> 	call	namei
  3150                              <1> 		; jsr r0,namei / get the i-number for the file
  3151                              <1> 	;jc	error
  3152                              <1> 		; br error3 / no such file, error
  3153 000049F5 7310                <1> 	jnc	short sysstat1
  3154                              <1> 	; pop 	ecx
  3155                              <1> sysstat_err0:
  3156                              <1> 	; 'file not found !' error
  3157 000049F7 C705[5D700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3157 000049FF 0000                <1>
  3158 00004A01 E97FF2FFFF          <1> 	jmp	error
  3159                              <1> 
  3160 00004A06 00                  <1> statx: db 0
  3161                              <1> 
  3162                              <1> sysstat1: ; 1:
  3163 00004A07 E8C0080000          <1> 	call	iget
  3164                              <1> 		; jsr r0,iget / get the i-node into core
  3165                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3166                              <1> 	; 02/09/2015
  3167 00004A0C 8F05[28700000]      <1> 	pop	dword [u.base]
  3168                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3169 00004A12 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3170 00004A17 730A                <1> 	jnc 	short sysstat2
  3171                              <1> sysstat_err1:
  3172 00004A19 A3[5D700000]        <1> 	mov	dword [u.error], eax ; error code
  3173 00004A1E E962F2FFFF          <1> 	jmp	error
  3174                              <1> sysstat2:
  3175 00004A23 A0[EA6F0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3176 00004A28 AA                  <1> 	stosb
  3177 00004A29 FF05[28700000]      <1> 	inc 	dword [u.base]
  3178                              <1> 	;dec 	cx
  3179                              <1> 	; 24/12/2021
  3180 00004A2F 49                  <1> 	dec	ecx
  3181 00004A30 7505                <1> 	jnz	short sysstat3
  3182 00004A32 E835000000          <1> 	call	sysstat_gpa
  3183                              <1> 	;jc	short sysstat_err1
  3184                              <1> sysstat3:
  3185 00004A37 A0[EB6F0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3186 00004A3C AA                  <1> 	stosb
  3187                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3188 00004A3D FF05[28700000]      <1> 	inc 	dword [u.base]
  3189                              <1> 	;;dec 	word [u.pcount]
  3190                              <1> 	;dec	cx
  3191 00004A43 49                  <1> 	dec	ecx ; 24/12/2021
  3192 00004A44 7505                <1> 	jnz	short sysstat4
  3193 00004A46 E821000000          <1> 	call	sysstat_gpa
  3194                              <1> 	;jc	short sysstat_err1	
  3195                              <1> sysstat4:
  3196 00004A4B BE[D66C0000]        <1> 	mov	esi, inode
  3197                              <1> 		; mov $inode,r2 / r2 points to i-node
  3198                              <1> sysstat5: ; 1:
  3199 00004A50 A4                  <1> 	movsb
  3200                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3201 00004A51 FF05[28700000]      <1> 	inc 	dword [u.base]
  3202                              <1> 	;;dec 	word [u.pcount]
  3203                              <1> 	;dec 	cx
  3204                              <1> 	; 24/12/2021
  3205 00004A57 49                  <1> 	dec	ecx
  3206 00004A58 7505                <1> 	jnz	short sysstat6
  3207 00004A5A E80D000000          <1> 	call	sysstat_gpa
  3208                              <1> 	;jc	short sysstat_err1
  3209                              <1> sysstat6:		
  3210 00004A5F 81FE[F66C0000]      <1> 	cmp	esi, inode + 32
  3211                              <1> 		; cmp r2,$inode+32 / done?
  3212 00004A65 75E9                <1> 	jne	short sysstat5
  3213                              <1> 		; bne 1b / no, go back
  3214 00004A67 E939F2FFFF          <1> 	jmp	sysret
  3215                              <1> 		; br sysret3 / return through sysret
  3216                              <1> 	;
  3217                              <1> sysstat_gpa: ; get physical address of file status buffer
  3218                              <1> 	; 02/09/2015
  3219 00004A6C 8B1D[28700000]      <1> 	mov 	ebx, [u.base]
  3220                              <1> 	; 07/10/2015
  3221 00004A72 E8AFE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3222                              <1> 	;jc	short sysstat_gpa1
  3223 00004A77 72A0                <1> 	jc	short sysstat_err1
  3224                              <1> 	; 18/10/2015
  3225 00004A79 89C7                <1> 	mov	edi, eax ; physical address
  3226                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3227                              <1> ;sysstat_gpa1:
  3228 00004A7B C3                  <1> 	retn
  3229                              <1> 
  3230                              <1> fclose:
  3231                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3232                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3233                              <1> 	;            (32 bit offset pointer modification)
  3234                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3235                              <1> 	;
  3236                              <1> 	; Given the file descriptor (index to the u.fp list)
  3237                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3238                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3239                              <1> 	; u.fp list is cleared. If all the processes that opened
  3240                              <1> 	; that file close it, then fsp etry is freed and the file
  3241                              <1> 	; is closed. If not a return is taken. 
  3242                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3243                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3244                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3245                              <1> 	; a check is made to see if the file is special.	
  3246                              <1> 	;
  3247                              <1> 	; INPUTS ->
  3248                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3249                              <1> 	;    u.fp - list of entries in the fsp table
  3250                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3251                              <1> 	; OUTPUTS ->
  3252                              <1> 	;    r1 - contains the same file descriptor
  3253                              <1> 	;    r2 - contains i-number
  3254                              <1> 	;
  3255                              <1> 	; ((AX = R1))
  3256                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3257                              <1> 	;
  3258                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3259                              <1> 	;              if i-number of the file is 0. (error)  	
  3260                              <1> 	;
  3261                              <1> 	;movzx	edx, ax ; **
  3262                              <1> 	; 24/12/2021
  3263                              <1> 	;movzx	edx, al
  3264 00004A7C 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3265 00004A7E 50                  <1> 	push	eax ; ***
  3266                              <1> 	;push	ax ; ***
  3267                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3268                              <1> 			     ; / the index to u.fp list)
  3269 00004A7F E83A000000          <1> 	call	getf
  3270                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3271                              <1> 			    ; / cdev has device =, u.fofp 
  3272                              <1> 			    ; / points to 3rd word of fsp entry
  3273 00004A84 6683F801            <1> 	cmp	ax, 1 ; r1
  3274                              <1> 		; tst r1 / is i-number 0?
  3275 00004A88 7232                <1> 	jb	short fclose_2
  3276                              <1> 		; beq 1f / yes, i-node not active so return
  3277                              <1> 		; tst (r0)+ / no, jump over error return
  3278 00004A8A 89D3                <1> 	mov	ebx, edx ; **
  3279                              <1> 	; 24/12/2021
  3280 00004A8C 89C2                <1> 	mov	edx, eax ; *
  3281                              <1> 	;mov 	dx, ax ; *
  3282                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3283                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3284                              <1> 			    ; / which is index to u.fp ; **
  3285 00004A8E C683[0E700000]00    <1> 	mov	byte [ebx+u.fp], 0
  3286                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3287 00004A95 8B1D[18700000]      <1> 	mov	ebx, [u.fofp]
  3288                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3289                              <1> fclose_0:
  3290 00004A9B FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3291                              <1> 		; decb 2(r1) / decrement the number of processes 
  3292                              <1> 			   ; / that have opened the file
  3293 00004A9E 791C                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3294                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3295                              <1> 	;
  3296                              <1> 	; 24/12/2021
  3297 00004AA0 52                  <1> 	push	edx ; *
  3298                              <1> 	;push	dx ; *
  3299                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3300                              <1> 	;xor	ax, ax ; 0
  3301                              <1> 	; 24/12/2021
  3302 00004AA1 31C0                <1> 	xor	eax, eax
  3303 00004AA3 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3304                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3305 00004AA7 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3306                              <1> 		; tstb	3(r1) / has this file been deleted
  3307 00004AAA 20C0                <1> 	and	al, al
  3308 00004AAC 7408                <1> 	jz	short fclose_1
  3309                              <1> 		; beq 2f / no, branch
  3310 00004AAE 6689D0              <1> 	mov	ax, dx ; *
  3311                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3312                              <1> 	; AX = inode number
  3313 00004AB1 E85A040000          <1> 	call	anyi
  3314                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3315                              <1> 			    ; / check if file appears in fsp again
  3316                              <1> fclose_1: ; 2:
  3317                              <1> 	; 24/12/2021
  3318 00004AB6 58                  <1> 	pop	eax ; * 
  3319                              <1> 	;pop	ax ; *
  3320                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3321 00004AB7 E8A8100000          <1> 	call	iclose ; close if it is special file 
  3322                              <1> 		; jsr r0,iclose / check to see if its a special file
  3323                              <1> fclose_2: ; 1:
  3324                              <1> 	; 24/12/2021
  3325 00004ABC 58                  <1> 	pop	eax ; ***
  3326                              <1> 	;pop	ax ; ***
  3327                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3328 00004ABD C3                  <1> 	retn
  3329                              <1> 		; rts r0
  3330                              <1> 
  3331                              <1> getf:	; / get the device number and the i-number of an open file
  3332                              <1> 	; 13/05/2015
  3333                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3334                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3335                              <1> 	;
  3336 00004ABE 89C3                <1> 	mov	ebx, eax
  3337                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3338 00004AC0 83FB0A              <1> 	cmp	ebx, 10
  3339                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3340 00004AC3 730A                <1>         jnb	short getf2 ; 13/05/2015
  3341                              <1> 	;jnb     error
  3342                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3343                              <1> 			    ; / index in fsp table
  3344 00004AC5 8A9B[0E700000]      <1> 	mov	bl, [ebx+u.fp]
  3345                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3346                              <1> 		                  ; / in fsp table
  3347 00004ACB 08DB                <1> 	or	bl, bl
  3348 00004ACD 7503                <1> 	jnz	short getf3
  3349                              <1> 	;jz	short getf4
  3350                              <1> 		; beq 1f / if its zero return
  3351                              <1> getf2:
  3352                              <1> 	; 'File not open !' error (ax=0)
  3353 00004ACF 29C0                <1> 	sub	eax, eax
  3354 00004AD1 C3                  <1> 	retn
  3355                              <1> getf3:	
  3356                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3357                              <1> 	;
  3358                              <1> 	; 'fsp' table (10 bytes/entry)
  3359                              <1> 	; bit 15				   bit 0
  3360                              <1> 	; ---|-------------------------------------------
  3361                              <1> 	; r/w|		i-number of open file
  3362                              <1> 	; ---|-------------------------------------------
  3363                              <1> 	;		   device number
  3364                              <1> 	; -----------------------------------------------
  3365                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3366                              <1> 	; -----------------------------------------------
  3367                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3368                              <1> 	; ----------------------|------------------------
  3369                              <1> 	;  flag that says file 	| number of processes
  3370                              <1> 	;   has been deleted	| that have file open 
  3371                              <1> 	; ----------------------|------------------------
  3372                              <1> 	;
  3373 00004AD2 B80A000000          <1> 	mov	eax, 10
  3374 00004AD7 F6E3                <1> 	mul	bl
  3375 00004AD9 BB[D06D0000]        <1> 	mov	ebx, fsp - 6 ; the 3rd word in the fsp entry
  3376 00004ADE 01C3                <1> 	add	ebx, eax
  3377                              <1> 		; asl r1
  3378                              <1> 		; asl r1 / multiply by 8 to get index into 
  3379                              <1> 		       ; / fsp table entry
  3380                              <1> 		; asl r1
  3381                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3382                              <1> 			      ; / in the fsp entry
  3383 00004AE0 891D[18700000]      <1> 	mov	[u.fofp], ebx
  3384                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3385                              <1> 			      ; / in fsp entry in u.fofp
  3386 00004AE6 4B                  <1> 	dec	ebx
  3387 00004AE7 4B                  <1> 	dec	ebx
  3388 00004AE8 668B03              <1> 	mov	ax, [ebx]
  3389                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3390 00004AEB 66A3[EE6F0000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3391                              <1> 			     ;;dev number is in 1 byte
  3392                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3393 00004AF1 4B                  <1> 	dec	ebx
  3394 00004AF2 4B                  <1> 	dec	ebx
  3395 00004AF3 668B03              <1> 	mov	ax, [ebx]
  3396                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3397                              <1> getf4:	; 1:
  3398 00004AF6 C3                  <1> 	retn
  3399                              <1> 		; rts r0
  3400                              <1> 
  3401                              <1> namei:
  3402                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3403                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3404                              <1> 	; 18/10/2015 (nbase, ncount)
  3405                              <1> 	; 12/10/2015
  3406                              <1> 	; 21/08/2015
  3407                              <1> 	; 18/07/2015
  3408                              <1> 	; 02/07/2015
  3409                              <1> 	; 17/06/2015
  3410                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3411                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3412                              <1> 	;
  3413                              <1> 	; 'namei' takes a file path name and returns i-number of
  3414                              <1> 	; the file in the current directory or the root directory
  3415                              <1> 	; (if the first character of the pathname is '/').	
  3416                              <1> 	;
  3417                              <1> 	; INPUTS ->
  3418                              <1> 	;    u.namep - points to a file path name
  3419                              <1> 	;    u.cdir - i-number of users directory
  3420                              <1> 	;    u.cdev - device number on which user directory resides	
  3421                              <1> 	; OUTPUTS ->
  3422                              <1> 	;    r1 - i-number of file
  3423                              <1> 	;    cdev
  3424                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3425                              <1> 	;               occurs in the search for file path name.
  3426                              <1> 	;	        If no match u.dirb points to the end of 
  3427                              <1> 	;               the directory and r1 = i-number of the current
  3428                              <1> 	;	        directory.	
  3429                              <1> 	; ((AX = R1))
  3430                              <1> 	;
  3431                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3432                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3433                              <1> 	;
  3434                              <1> 
  3435 00004AF7 66A1[0C700000]      <1> 	mov	ax, [u.cdir]
  3436                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3437                              <1> 			      ; / in r1
  3438 00004AFD 668B15[52700000]    <1> 	mov	dx, [u.cdrv]
  3439 00004B04 668915[EE6F0000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3440                              <1> 				    ; device/drive number is in 1 byte, 
  3441                              <1> 				    ; not in 1 word!
  3442                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3443                              <1> 				; / into cdev
  3444                              <1> 	; 12/10/2015
  3445                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3446                              <1>       	 ; convert virtual (pathname) addr to physical address
  3447 00004B0B E824010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3448                              <1> 		; esi = physical address of [u.namep]
  3449                              <1> 		; ecx = byte count in the page
  3450 00004B10 803E2F              <1> 	cmp	byte [esi], '/'
  3451                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3452 00004B13 751D                <1> 	jne	short namei_1
  3453                              <1> 		; bne 1f
  3454 00004B15 FF05[20700000]      <1> 	inc	dword [u.namep]
  3455                              <1> 		; inc u.namep / go to next char
  3456                              <1> 	;dec	cx ; remain byte count in the page
  3457                              <1> 	; 24/12/2021
  3458 00004B1B 49                  <1> 	dec	ecx
  3459 00004B1C 7506                <1> 	jnz	short namei_0
  3460                              <1> 	; 12/10/2015
  3461 00004B1E E811010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3462                              <1> 		; esi = physical address (page start + offset)
  3463                              <1> 		; ecx = byte count in the page
  3464 00004B23 4E                  <1> 	dec	esi
  3465                              <1> namei_0:
  3466 00004B24 46                  <1> 	inc 	esi  ; go to next char
  3467 00004B25 66A1[F86F0000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3468                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3469 00004B2B C605[EE6F0000]00    <1> 	mov	byte [cdev], 0
  3470                              <1> 		; clr cdev / clear device number
  3471                              <1> namei_1: ; 1:
  3472 00004B32 F606FF              <1> 	test	byte [esi], 0FFh
  3473                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3474 00004B35 74BF                <1> 	jz	short getf4
  3475                              <1> 	;jz	nig
  3476                              <1> 		; tstb *u.namep / is the character in file name a nul
  3477                              <1> 		; beq nig / yes, end of file name reached; 
  3478                              <1> 			; / branch to "nig"
  3479                              <1> namei_2: ; 1:
  3480                              <1> 	; 18/10/2015
  3481 00004B37 8935[80700000]      <1> 	mov 	[nbase], esi
  3482 00004B3D 66890D[84700000]    <1> 	mov 	[ncount], cx
  3483                              <1> 	;
  3484                              <1> 	;mov	dx, 2
  3485 00004B44 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3486 00004B46 E857080000          <1> 	call	access
  3487                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3488                              <1> 	; 'access' will not return here if user has not "r" permission !
  3489 00004B4B 66F705[D66C0000]00- <1> 	test 	word [i.flgs], 4000h
  3489 00004B53 40                  <1>
  3490                              <1> 		; bit $40000,i.flgs / directory i-node?
  3491 00004B54 746A                <1>         jz      short namei_err
  3492                              <1> 		; beq error3 / no, got an error
  3493                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3494 00004B56 31C0                <1> 	xor	eax, eax
  3495 00004B58 A3[24700000]        <1> 	mov	[u.off], eax ; 0
  3496 00004B5D 66A1[DA6C0000]      <1> 	mov	ax, [i.size]
  3497 00004B63 A3[1C700000]        <1> 	mov	[u.dirp], eax
  3498                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3499                              <1> 		; clr u.off / u.off is file offset used by user
  3500 00004B68 C705[18700000]-     <1> 	mov	dword [u.fofp], u.off
  3500 00004B6E [24700000]          <1>
  3501                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3502                              <1> 				  ; / the offset portion of fsp entry
  3503                              <1> namei_3: ; 2:
  3504 00004B72 C705[28700000]-     <1> 	mov	dword [u.base], u.dirbuf
  3504 00004B78 [3A700000]          <1>
  3505                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3506                              <1> 				    ; / copied from a directory
  3507 00004B7C C705[2C700000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3507 00004B84 0000                <1>
  3508                              <1>  		; mov $10.,u.count / u.count is byte count 
  3509                              <1> 				 ; / for reads and writes
  3510 00004B86 66A1[EA6F0000]      <1> 	mov 	ax, [ii]
  3511                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3512 00004B8C FE05[6F700000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3513 00004B92 E80C090000          <1>     	call	readi
  3514                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3515                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3516 00004B97 8B0D[30700000]      <1> 	mov 	ecx, [u.nread]
  3517 00004B9D 09C9                <1> 	or 	ecx, ecx
  3518                              <1> 		; tst u.nread
  3519 00004B9F 741B                <1> 	jz	short nib
  3520                              <1> 		; ble nib / gives error return
  3521                              <1> 	;
  3522 00004BA1 668B1D[3A700000]    <1> 	mov 	bx, [u.dirbuf]
  3523 00004BA8 6621DB              <1> 	and 	bx, bx       
  3524                              <1> 		; tst u.dirbuf /
  3525 00004BAB 7522                <1> 	jnz	short namei_4
  3526                              <1> 		; bne 3f / branch when active directory entry 
  3527                              <1> 		       ; / (i-node word in entry non zero)
  3528 00004BAD A1[24700000]        <1> 	mov	eax, [u.off]
  3529 00004BB2 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3530 00004BB5 A3[1C700000]        <1> 	mov	[u.dirp], eax
  3531                              <1> 		; mov u.off,u.dirp
  3532                              <1> 		; sub $10.,u.dirp
  3533 00004BBA EBB6                <1> 	jmp	short namei_3
  3534                              <1> 		; br 2b
  3535                              <1> 
  3536                              <1> 	; 18/07/2013
  3537                              <1> nib: 
  3538 00004BBC 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3539 00004BBE F9                  <1> 	stc
  3540                              <1> nig:
  3541 00004BBF C3                  <1> 	retn
  3542                              <1> 
  3543                              <1> namei_err:
  3544                              <1> 	; 16/06/2015
  3545 00004BC0 C705[5D700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3545 00004BC8 0000                <1>
  3546 00004BCA E9B6F0FFFF          <1> 	jmp	error
  3547                              <1> 
  3548                              <1> namei_4: ; 3:
  3549                              <1> 	; 18/10/2015
  3550                              <1> 	; 12/10/2015
  3551                              <1> 	; 21/08/2015
  3552                              <1> 	; 18/07/2015
  3553 00004BCF 8B2D[20700000]      <1> 	mov	ebp, [u.namep]
  3554                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3555 00004BD5 BF[3C700000]        <1> 	mov 	edi, u.dirbuf + 2
  3556                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3557                              <1> 	; 18/10/2015
  3558 00004BDA 8B35[80700000]      <1> 	mov	esi, [nbase]	
  3559 00004BE0 668B0D[84700000]    <1> 	mov	cx, [ncount]
  3560                              <1> 	;
  3561 00004BE7 6621C9              <1> 	and	cx, cx
  3562 00004BEA 7505                <1> 	jnz	short namei_5	
  3563                              <1> 	;
  3564 00004BEC E849000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3565                              <1> 		; esi = physical address (page start + offset)
  3566                              <1> 		; ecx = byte count in the page
  3567                              <1> namei_5: ; 3:
  3568 00004BF1 45                  <1> 	inc	ebp ; 18/07/2015
  3569 00004BF2 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3570                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3571 00004BF3 08C0                <1> 	or 	al, al
  3572 00004BF5 741C                <1> 	jz 	short namei_7
  3573                              <1> 		; beq 3f / if char is nul, then the last char in string
  3574                              <1> 			; / has been moved
  3575 00004BF7 3C2F                <1> 	cmp	al, '/'
  3576                              <1> 		; cmp r4,$'/ / is char a </>
  3577 00004BF9 7418                <1> 	je 	short namei_7
  3578                              <1> 		; beq 3f	
  3579                              <1> 	; 24/12/2021
  3580 00004BFB 49                  <1> 	dec	ecx
  3581                              <1> 	; 12/10/2015
  3582                              <1> 	;dec	cx ; remain byte count in the page
  3583 00004BFC 7505                <1> 	jnz	short namei_6
  3584 00004BFE E837000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3585                              <1> 		; esi = physical address (page start + offset)
  3586                              <1> 		; ecx = byte count in the page
  3587                              <1> namei_6:
  3588 00004C03 81FF[4A700000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3589                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3590                              <1> 				     ; / all 8 bytes of file name
  3591 00004C09 74E6                <1> 	je	short namei_5
  3592                              <1> 		; beq 3b
  3593 00004C0B AE                  <1> 	scasb	
  3594                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3595                              <1> 			      ; / char read from directory
  3596 00004C0C 74E3                <1> 	je 	short namei_5
  3597                              <1> 		; beq 3b / branch if chars match
  3598                              <1> namei_9:
  3599 00004C0E E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3600                              <1> 		; br 2b / file names do not match go to next directory entry
  3601                              <1> namei_7: ; 3:
  3602 00004C13 81FF[4A700000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3603                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3604 00004C19 7406                <1> 	je	short namei_8
  3605                              <1> 		; beq 3f
  3606 00004C1B 8A27                <1> 	mov 	ah, [edi]
  3607                              <1> 	;inc 	edi 
  3608 00004C1D 20E4                <1> 	and 	ah, ah
  3609                              <1> 		; tstb (r3)+ /
  3610                              <1>         ;jnz	namei_3
  3611                              <1> 		; bne 2b
  3612                              <1> 	; 24/12/2021
  3613 00004C1F 75ED                <1> 	jnz	short namei_9	
  3614                              <1> namei_8: ; 3
  3615 00004C21 892D[20700000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3616                              <1> 		; mov r2,u.namep / u.namep points to char 
  3617                              <1> 			       ; / following a / or nul
  3618                              <1> 	;mov	bx, [u.dirbuf]
  3619                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3620                              <1> 				; / entry to r1
  3621 00004C27 20C0                <1> 	and 	al, al
  3622                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3623                              <1> 		      ;  / if r4 = </> then go to next directory
  3624                              <1> 	;mov	ax, bx
  3625 00004C29 66A1[3A700000]      <1> 	mov 	ax, [u.dirbuf] ; 17/06/2015
  3626                              <1>   	; 24/12/2021
  3627 00004C2F E901FFFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3628                              <1> 	;jnz	namei_2 
  3629                              <1> 		; bne 1b
  3630                              <1> 	; AX = i-number of the file
  3631                              <1> ;;nig:
  3632                              <1> 	;retn	; 24/12/2021
  3633                              <1> 		; tst (r0)+ / gives non-error return
  3634                              <1> ;;nib:
  3635                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3636                              <1> 		       ; ax = 0 -> file not found 
  3637                              <1> ;;	stc	; 27/05/2013
  3638                              <1> ;;	retn
  3639                              <1> 		; rts r0
  3640                              <1> 
  3641                              <1> trans_addr_nmbp:
  3642                              <1> 	; 18/10/2015
  3643                              <1> 	; 12/10/2015
  3644 00004C34 8B2D[20700000]      <1> 	mov 	ebp, [u.namep]
  3645                              <1> trans_addr_nm: 
  3646                              <1> 	; Convert virtual (pathname) address to physical address
  3647                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3648                              <1> 	; 18/10/2015
  3649                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3650                              <1> 	; 02/07/2015
  3651                              <1> 	; 17/06/2015
  3652                              <1> 	; 16/06/2015
  3653                              <1> 	;
  3654                              <1> 	; INPUTS: 
  3655                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3656                              <1> 	;	[u.pgdir] = user's page directory
  3657                              <1> 	; OUTPUT:
  3658                              <1> 	;       esi = physical address of the pathname
  3659                              <1> 	;	ecx = remain byte count in the page
  3660                              <1> 	;
  3661                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3662                              <1> 	;
  3663 00004C3A 833D[65700000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3664 00004C41 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3665                              <1> 				     ; it is already physical address
  3666 00004C43 50                  <1>    	push	eax	
  3667 00004C44 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3668 00004C46 E8DBE6FFFF          <1>        	call	get_physical_addr ; get physical address
  3669 00004C4B 7204                <1> 	jc	short tr_addr_nm_err
  3670                              <1> 	; 18/10/2015
  3671                              <1> 	; eax = physical address 
  3672                              <1> 	; cx = remain byte count in page (1-4096) 
  3673                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3674 00004C4D 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3675 00004C4F 58                  <1> 	pop	eax 
  3676 00004C50 C3                  <1> 	retn
  3677                              <1> 
  3678                              <1> tr_addr_nm_err:
  3679 00004C51 A3[5D700000]        <1> 	mov	[u.error], eax
  3680                              <1> 	;pop 	eax
  3681 00004C56 E92AF0FFFF          <1> 	jmp	error
  3682                              <1> 
  3683                              <1> trans_addr_nmk:
  3684                              <1> 	; 12/10/2015
  3685                              <1> 	; 02/07/2015
  3686 00004C5B 8B35[20700000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3687 00004C61 66B90010            <1> 	mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3688 00004C65 C3                  <1> 	retn
  3689                              <1> 
  3690                              <1> syschdir:
  3691                              <1> 	; / makes the directory specified in the argument
  3692                              <1> 	; / the current directory
  3693                              <1> 	;
  3694                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3695                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3696                              <1> 	;
  3697                              <1> 	; 'syschdir' makes the directory specified in its argument
  3698                              <1> 	; the current working directory.
  3699                              <1> 	;
  3700                              <1> 	; Calling sequence:
  3701                              <1> 	;	syschdir; name
  3702                              <1> 	; Arguments:
  3703                              <1> 	;	name - address of the path name of a directory
  3704                              <1> 	;	       terminated by nul byte.	
  3705                              <1> 	; Inputs: -
  3706                              <1> 	; Outputs: -
  3707                              <1> 	; ...............................................................
  3708                              <1> 	;				
  3709                              <1> 	; Retro UNIX 8086 v1 modification:
  3710                              <1> 	;	 The user/application program puts address of 
  3711                              <1> 	;	 the path name in BX register as 'syschdir' 
  3712                              <1> 	; 	 system call argument.
  3713                              <1> 
  3714 00004C66 891D[20700000]      <1> 	mov	[u.namep], ebx
  3715                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3716 00004C6C E886FEFFFF          <1> 	call	namei
  3717                              <1> 		; jsr r0,namei / find its i-number
  3718                              <1> 	;jc	error
  3719                              <1> 		; br error3
  3720 00004C71 730F                <1> 	jnc	short syschdir0
  3721                              <1> 	; 'directory not found !' error
  3722 00004C73 C705[5D700000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3722 00004C7B 0000                <1>
  3723 00004C7D E903F0FFFF          <1> 	jmp	error
  3724                              <1> syschdir0:
  3725 00004C82 E81B070000          <1> 	call	access
  3726                              <1> 		; jsr r0,access; 2 / get i-node into core
  3727 00004C87 66F705[D66C0000]00- <1> 	test	word [i.flgs], 4000h
  3727 00004C8F 40                  <1>
  3728                              <1> 		; bit $40000,i.flgs / is it a directory?
  3729                              <1> 	;jz	error 
  3730                              <1> 		; beq error3 / no error
  3731 00004C90 750F                <1> 	jnz	short syschdir1
  3732 00004C92 C705[5D700000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3732 00004C9A 0000                <1>
  3733 00004C9C E9E4EFFFFF          <1> 	jmp	error
  3734                              <1> syschdir1:
  3735 00004CA1 66A3[0C700000]      <1> 	mov	[u.cdir], ax
  3736                              <1> 		; mov r1,u.cdir / move i-number to users 
  3737                              <1> 			      ; / current directory
  3738 00004CA7 66A1[EE6F0000]      <1> 	mov	ax, [cdev]
  3739 00004CAD 66A3[52700000]      <1> 	mov	[u.cdrv], ax
  3740                              <1> 		; mov cdev,u.cdev / move its device to users 
  3741                              <1> 			        ; / current device
  3742 00004CB3 E9EDEFFFFF          <1> 	jmp	sysret
  3743                              <1> 		; br sysret3
  3744                              <1> 	
  3745                              <1> syschmod: ; < change mode of file >
  3746                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3747                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3748                              <1> 	;
  3749                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3750                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3751                              <1> 	; changed to 'mode'.
  3752                              <1> 	;
  3753                              <1> 	; Calling sequence:
  3754                              <1> 	;	syschmod; name; mode
  3755                              <1> 	; Arguments:
  3756                              <1> 	;	name - address of the file name
  3757                              <1> 	;	       terminated by null byte.
  3758                              <1> 	;	mode - (new) mode/flags < attributes >
  3759                              <1> 	;	
  3760                              <1> 	; Inputs: -
  3761                              <1> 	; Outputs: -
  3762                              <1> 	; ...............................................................
  3763                              <1> 	;				
  3764                              <1> 	; Retro UNIX 8086 v1 modification: 
  3765                              <1> 	;       'syschmod' system call has two arguments; so,
  3766                              <1> 	;	* 1st argument, name is pointed to by BX register
  3767                              <1> 	;	* 2nd argument, mode is in CX register
  3768                              <1> 	;
  3769                              <1> 	; Mode bits (Flags):
  3770                              <1> 	;	bit 0 - write permission for non-owner (1)
  3771                              <1> 	;	bit 1 - read permission for non-owner (2)
  3772                              <1> 	;	bit 2 - write permission for owner (4)
  3773                              <1> 	;	bit 3 - read permission for owner (8)
  3774                              <1> 	;	bit 4 - executable flag (16) 	
  3775                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3776                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3777                              <1> 	;	bit 12 - large file flag (4096)
  3778                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3779                              <1> 	;	bit 14 - directory flag (16384)
  3780                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3781                              <1> 
  3782                              <1> 	; / name; mode
  3783 00004CB8 E814000000          <1> 	call	isown
  3784                              <1> 		;jsr r0,isown / get the i-node and check user status
  3785 00004CBD 66F705[D66C0000]00- <1> 	test	word [i.flgs], 4000h
  3785 00004CC5 40                  <1>
  3786                              <1> 		; bit	$40000,i.flgs / directory?
  3787 00004CC6 7402                <1> 	jz	short syschmod1
  3788                              <1> 		; beq 2f / no
  3789                              <1> 	; AL = (new) mode
  3790 00004CC8 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3791                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3792                              <1> 			   ; / executable modes
  3793                              <1> syschmod1: ; 2:
  3794 00004CCA A2[D66C0000]        <1> 	mov	[i.flgs], al	
  3795                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3796 00004CCF EB42                <1> 	jmp	short isown1
  3797                              <1> 		; br 1f
  3798                              <1> 
  3799                              <1> isown:
  3800                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3801                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3802                              <1> 	;
  3803                              <1> 	; 'isown' is given a file name (the 1st argument).
  3804                              <1> 	;  It find the i-number of that file via 'namei' 
  3805                              <1> 	;  then gets the i-node into core via 'iget'.
  3806                              <1> 	;  It then tests to see if the user is super user. 
  3807                              <1> 	;  If not, it cheks to see if the user is owner of 
  3808                              <1> 	;  the file. If he is not an error occurs.
  3809                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3810                              <1> 	;  the inode has been modificed and the 2nd argument of
  3811                              <1> 	;  the call is put in r2.
  3812                              <1> 	;
  3813                              <1> 	; INPUTS ->
  3814                              <1> 	;    arguments of syschmod and syschown calls
  3815                              <1> 	; OUTPUTS ->
  3816                              <1> 	;    u.uid - id of user
  3817                              <1> 	;    imod - set to a 1
  3818                              <1> 	;    r2 - contains second argument of the system call				 	
  3819                              <1> 	;
  3820                              <1> 	;   ((AX=R2) output as 2nd argument)
  3821                              <1> 	;
  3822                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  3823                              <1> 	;
  3824                              <1> 		; jsr r0,arg2 / u.namep points to file name
  3825                              <1> 	;; ! 2nd argument on top of stack !
  3826                              <1> 	;; 22/06/2015 - 32 bit modifications
  3827                              <1> 	;; 07/07/2013
  3828 00004CD1 891D[20700000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  3829 00004CD7 51                  <1> 	push 	ecx ;; 2nd argument
  3830                              <1> 	;;
  3831 00004CD8 E81AFEFFFF          <1> 	call	namei
  3832                              <1> 		; jsr r0,namei / get its i-number
  3833                              <1>        ; Retro UNIX 8086 v1 modification !
  3834                              <1>        ; ax = 0 -> file not found 
  3835                              <1> 	;and	ax, ax
  3836                              <1> 	;jz	error
  3837                              <1> 	;jc	error ; 27/05/2013
  3838                              <1> 		; br error3
  3839 00004CDD 730F                <1> 	jnc	short isown0
  3840                              <1> 	; 'file not found !' error
  3841 00004CDF C705[5D700000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3841 00004CE7 0000                <1>
  3842 00004CE9 E997EFFFFF          <1> 	jmp	error
  3843                              <1> isown0:
  3844 00004CEE E8D9050000          <1> 	call	iget
  3845                              <1> 		; jsr r0,iget / get i-node into core
  3846 00004CF3 A0[54700000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  3847 00004CF8 08C0                <1> 	or	al, al
  3848                              <1> 		; tstb u.uid / super user?
  3849 00004CFA 7417                <1> 	jz	short isown1
  3850                              <1> 		; beq 1f / yes, branch
  3851 00004CFC 3A05[D96C0000]      <1> 	cmp	al, [i.uid]
  3852                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  3853                              <1> 				 ; / the file
  3854                              <1> 	;jne	error
  3855                              <1> 		; beq 1f / yes
  3856                              <1> 		; jmp error3 / no, error
  3857 00004D02 740F                <1> 	je	short isown1
  3858                              <1> 
  3859 00004D04 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  3859 00004D0C 0000                <1>
  3860                              <1> 			;  'permission denied !' error
  3861 00004D0E E972EFFFFF          <1> 	jmp	error
  3862                              <1> isown1: ; 1:
  3863 00004D13 E8C0060000          <1> 	call	setimod
  3864                              <1> 		; jsr r0,setimod / indicates 
  3865                              <1> 		;	       ; / i-node has been modified
  3866 00004D18 58                  <1> 	pop	eax ; 2nd argument
  3867                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  3868                              <1> 		       ; / (u.off put on stack with 2nd arg)
  3869 00004D19 C3                  <1> 	retn
  3870                              <1> 		; rts r0
  3871                              <1> 
  3872                              <1> ;;arg:  ; < get system call arguments >
  3873                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  3874                              <1> 	; of form:
  3875                              <1> 	;	sys 'routine' ; arg1
  3876                              <1> 	;		or
  3877                              <1> 	;	sys 'routine' ; arg1 ; arg2
  3878                              <1> 	;		or
  3879                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  3880                              <1> 	;	
  3881                              <1> 	; INPUTS ->
  3882                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  3883                              <1> 	;	This pointers's value is actually the value of
  3884                              <1> 	;	update pc at the the trap to sysent (unkni) is
  3885                              <1> 	;	made to process the sys instruction
  3886                              <1> 	;    r0 - contains the return address for the routine
  3887                              <1> 	;	that called arg. The data in the word pointer 
  3888                              <1> 	;	to by the return address is used as address
  3889                              <1> 	;	in which the extracted argument is stored   		
  3890                              <1> 	;    	
  3891                              <1> 	; OUTPUTS ->
  3892                              <1> 	;    'address' - contains the extracted argument 
  3893                              <1> 	;    u.sp+18 - is incremented by 2 
  3894                              <1> 	;    r1 - contains the extracted argument
  3895                              <1> 	;    r0 - points to the next instruction to be
  3896                              <1> 	;	 executed in the calling routine.
  3897                              <1> 	;
  3898                              <1>   
  3899                              <1> 	; mov u.sp,r1
  3900                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  3901                              <1> 			; / into argument of arg2
  3902                              <1> 	; add $2,18.(r1) / point pc on stack 
  3903                              <1> 			      ; / to next system argument
  3904                              <1> 	; rts r0
  3905                              <1> 
  3906                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  3907                              <1> 	; 'arg2' takes first argument in system call
  3908                              <1> 	;  (pointer to name of the file) and puts it in location
  3909                              <1> 	;  u.namep; takes second argument and puts it in u.off
  3910                              <1> 	;  and on top of the stack
  3911                              <1> 	;	
  3912                              <1> 	; INPUTS ->
  3913                              <1> 	;    u.sp, r0
  3914                              <1> 	;    	
  3915                              <1> 	; OUTPUTS ->
  3916                              <1> 	;    u.namep
  3917                              <1> 	;    u.off 
  3918                              <1> 	;    u.off pushed on stack
  3919                              <1> 	;    r1
  3920                              <1> 	;
  3921                              <1> 
  3922                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  3923                              <1> 				; / first arg in sys call
  3924                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  3925                              <1> 				; / second arg in sys call
  3926                              <1> 	; mov r0,r1 / r0 points to calling routine
  3927                              <1> 	; mov (sp),r0 / put operation code back in r0
  3928                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  3929                              <1> 			; / on stack
  3930                              <1> 	; jmp (r1) / return to calling routine
  3931                              <1> 
  3932                              <1> syschown: ; < change owner of file >
  3933                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3934                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3935                              <1> 	;
  3936                              <1> 	; 'syschown' changes the owner of the file whose name is given
  3937                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  3938                              <1> 	; changed to 'owner'
  3939                              <1> 	;
  3940                              <1> 	; Calling sequence:
  3941                              <1> 	;	syschown; name; owner
  3942                              <1> 	; Arguments:
  3943                              <1> 	;	name - address of the file name
  3944                              <1> 	;	       terminated by null byte.
  3945                              <1> 	;	owner - (new) owner (number/ID)
  3946                              <1> 	;	
  3947                              <1> 	; Inputs: -
  3948                              <1> 	; Outputs: -
  3949                              <1> 	; ...............................................................
  3950                              <1> 	;				
  3951                              <1> 	; Retro UNIX 8086 v1 modification: 
  3952                              <1> 	;       'syschown' system call has two arguments; so,
  3953                              <1> 	;	* 1st argument, name is pointed to by BX register
  3954                              <1> 	;	* 2nd argument, owner number is in CX register
  3955                              <1> 	;
  3956                              <1> 	; / name; owner
  3957 00004D1A E8B2FFFFFF          <1> 	call	isown
  3958                              <1> 		; jsr r0,isown / get the i-node and check user status
  3959 00004D1F 803D[54700000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  3960                              <1> 		; tstb u.uid / super user
  3961 00004D26 7418                <1> 	jz	short syschown1
  3962                              <1> 		; beq 2f / yes, 2f
  3963 00004D28 F605[D66C0000]20    <1>         test    byte [i.flgs], 20h ; 32
  3964                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  3965                              <1> 	;jnz	error
  3966                              <1> 		; bne 3f / yes error, could create Trojan Horses
  3967 00004D2F 740F                <1> 	jz	short syschown1
  3968                              <1> 	; 'permission denied !'
  3969 00004D31 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  3969 00004D39 0000                <1>
  3970 00004D3B E945EFFFFF          <1> 	jmp	error
  3971                              <1> syschown1: ; 2:
  3972                              <1> 	; AL = owner (number/ID)
  3973 00004D40 A2[D96C0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  3974                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  3975                              <1> 			       ; / in the i-node
  3976 00004D45 E95BEFFFFF          <1> 	jmp	sysret
  3977                              <1> 	; 1: 
  3978                              <1> 		; jmp sysret4
  3979                              <1> 	; 3:
  3980                              <1> 		; jmp	error
  3981                              <1> 
  3982                              <1> systime: ; / get time of year
  3983                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3984                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3985                              <1> 	;
  3986                              <1> 	; 20/06/2013
  3987                              <1> 	; 'systime' gets the time of the year.
  3988                              <1> 	; The present time is put on the stack.
  3989                              <1> 	;
  3990                              <1> 	; Calling sequence:
  3991                              <1> 	;	systime
  3992                              <1> 	; Arguments: -
  3993                              <1> 	;	
  3994                              <1> 	; Inputs: -
  3995                              <1> 	; Outputs: sp+2, sp+4 - present time
  3996                              <1> 	; ...............................................................
  3997                              <1> 	;	
  3998                              <1> 	; Retro UNIX 8086 v1 modification: 
  3999                              <1> 	;       'systime' system call will return to the user
  4000                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4001                              <1> 	;
  4002                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4003                              <1> 	;	system call for PC compatibility !!		 	
  4004                              <1> 
  4005 00004D4A E870EAFFFF          <1> 	call 	epoch
  4006 00004D4F A3[08700000]        <1> 	mov 	[u.r0], eax
  4007                              <1> 		; mov s.time,4(sp)
  4008                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4009                              <1> 				   ; / on the stack
  4010                              <1> 		; br sysret4
  4011 00004D54 E94CEFFFFF          <1> 	jmp	sysret 
  4012                              <1> 
  4013                              <1> sysstime: ; / set time
  4014                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4015                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4016                              <1> 	;
  4017                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4018                              <1> 	;
  4019                              <1> 	; Calling sequence:
  4020                              <1> 	;	sysstime
  4021                              <1> 	; Arguments: -
  4022                              <1> 	;	
  4023                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4024                              <1> 	; Outputs: -
  4025                              <1> 	; ...............................................................
  4026                              <1> 	;	
  4027                              <1> 	; Retro UNIX 8086 v1 modification: 
  4028                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4029                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4030                              <1> 	; 
  4031                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4032                              <1> 	;	to get sysstime system call arguments from the user;
  4033                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4034                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4035                              <1> 	;
  4036                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4037                              <1> 	;	system call for PC compatibility !!	
  4038                              <1> 
  4039 00004D59 803D[54700000]00    <1> 	cmp	byte [u.uid], 0
  4040                              <1> 		; tstb u.uid / is user the super user
  4041                              <1> 	;ja	error
  4042                              <1> 		; bne error4 / no, error
  4043 00004D60 760F                <1> 	jna	short systime1
  4044                              <1> 	; 'permission denied !'
  4045 00004D62 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4045 00004D6A 0000                <1>
  4046 00004D6C E914EFFFFF          <1> 	jmp	error
  4047                              <1> systime1:
  4048                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4049                              <1> 	; EBX = unix (epoch) time (from user)
  4050 00004D71 89D8                <1> 	mov	eax, ebx
  4051 00004D73 E8C9EBFFFF          <1> 	call 	set_date_time
  4052                              <1> 		; mov 4(sp),s.time
  4053                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4054 00004D78 E928EFFFFF          <1> 	jmp	sysret
  4055                              <1> 		; br sysret4
  4056                              <1> 
  4057                              <1> sysbreak:
  4058                              <1> 	; 18/10/2015
  4059                              <1> 	; 07/10/2015
  4060                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4061                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4062                              <1> 	;
  4063                              <1> 	; 'sysbreak' sets the programs break points. 
  4064                              <1> 	; It checks the current break point (u.break) to see if it is
  4065                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4066                              <1> 	; even address (if it was odd) and the area between u.break
  4067                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4068                              <1> 	; in u.break and control is passed to 'sysret'.
  4069                              <1> 	;
  4070                              <1> 	; Calling sequence:
  4071                              <1> 	;	sysbreak; addr
  4072                              <1> 	; Arguments: -
  4073                              <1> 	;	
  4074                              <1> 	; Inputs: u.break - current breakpoint
  4075                              <1> 	; Outputs: u.break - new breakpoint 
  4076                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4077                              <1> 	; ...............................................................
  4078                              <1> 	;	
  4079                              <1> 	; Retro UNIX 8086 v1 modification:
  4080                              <1> 	;	The user/application program puts breakpoint address
  4081                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4082                              <1> 	; 	(argument transfer method 1)
  4083                              <1> 	;
  4084                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4085                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4086                              <1> 	;  NOTE:
  4087                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4088                              <1> 	;	'u.break' address) of user's memory for original unix's
  4089                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4090                              <1> 
  4091                              <1> 		; mov u.break,r1 / move users break point to r1
  4092                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4093                              <1> 		; blos 1f / yes, 1f
  4094                              <1> 	; 23/06/2015
  4095 00004D7D 8B2D[34700000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4096                              <1> 	;and	ebp, ebp
  4097                              <1> 	;jz	short sysbreak_3 
  4098                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4099                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4100 00004D83 8B15[00700000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4101 00004D89 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4102                              <1> 	; 07/10/2015
  4103 00004D8C 891D[34700000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4104                              <1> 	;
  4105 00004D92 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4106                              <1> 			   ; with top of user's stack (virtual!)
  4107 00004D94 7327                <1> 	jnb	short sysbreak_3
  4108                              <1> 		; cmp r1,sp / is it the same or higher 
  4109                              <1> 			  ; / than the stack?
  4110                              <1> 		; bhis 1f / yes, 1f
  4111 00004D96 89DE                <1> 	mov	esi, ebx
  4112 00004D98 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4113 00004D9A 7621                <1> 	jna	short sysbreak_3 
  4114                              <1> 	;push	ebx
  4115                              <1> sysbreak_1:
  4116 00004D9C 89EB                <1> 	mov	ebx, ebp  
  4117 00004D9E E883E5FFFF          <1> 	call	get_physical_addr ; get physical address
  4118 00004DA3 0F82A8FEFFFF        <1> 	jc	tr_addr_nm_err
  4119                              <1> 	; 18/10/2015
  4120 00004DA9 89C7                <1> 	mov	edi, eax 
  4121 00004DAB 29C0                <1> 	sub	eax, eax ; 0
  4122                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4123 00004DAD 39CE                <1> 	cmp	esi, ecx
  4124 00004DAF 7302                <1> 	jnb	short sysbreak_2
  4125 00004DB1 89F1                <1> 	mov	ecx, esi
  4126                              <1> sysbreak_2:
  4127 00004DB3 29CE                <1> 	sub	esi, ecx
  4128 00004DB5 01CD                <1> 	add	ebp, ecx
  4129 00004DB7 F3AA                <1> 	rep 	stosb
  4130 00004DB9 09F6                <1> 	or	esi, esi
  4131 00004DBB 75DF                <1> 	jnz	short sysbreak_1
  4132                              <1> 	;
  4133                              <1> 		; bit $1,r1 / is it an odd address
  4134                              <1> 		; beq 2f / no, its even
  4135                              <1> 		; clrb (r1)+ / yes, make it even
  4136                              <1> 	; 2: / clear area between the break point and the stack
  4137                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4138                              <1> 		; bhis 1f / yes, quit
  4139                              <1> 		; clr (r1)+ / clear word
  4140                              <1> 		; br 2b / go back
  4141                              <1> 	;pop	ebx
  4142                              <1> sysbreak_3: ; 1:
  4143                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4144                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4145                              <1> 			; / in u.break (set new break point)
  4146                              <1> 		; br sysret4 / br sysret
  4147 00004DBD E9E3EEFFFF          <1> 	jmp	sysret
  4148                              <1> 
  4149                              <1> 
  4150                              <1> maknod: 
  4151                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4152                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4153                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4154                              <1> 	;
  4155                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4156                              <1> 	; for this i-node in the current directory.
  4157                              <1> 	;
  4158                              <1> 	; INPUTS ->
  4159                              <1> 	;    r1 - contains mode
  4160                              <1> 	;    ii - current directory's i-number	
  4161                              <1> 	;    	
  4162                              <1> 	; OUTPUTS ->
  4163                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4164                              <1> 	;    i.flgs - flags in new i-node 
  4165                              <1> 	;    i.uid - filled with u.uid
  4166                              <1> 	;    i.nlks - 1 is put in the number of links
  4167                              <1> 	;    i.ctim - creation time				
  4168                              <1> 	;    i.ctim+2 - modification time
  4169                              <1> 	;    imod - set via call to setimod
  4170                              <1> 	;	
  4171                              <1> 	; ((AX = R1)) input
  4172                              <1> 	;
  4173                              <1> 	; (Retro UNIX Prototype : 
  4174                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4175                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4176                              <1> 
  4177                              <1> 	; / r1 contains the mode
  4178 00004DC2 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4179                              <1> 		; bis	$100000,r1 / allocate flag set
  4180 00004DC5 6650                <1> 	push	ax ; * ; 24/12/2021
  4181                              <1> 		; mov r1,-(sp) / put mode on stack
  4182                              <1> 	; 31/07/2013
  4183 00004DC7 66A1[EA6F0000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4184                              <1> 		; mov ii,r1 / move current i-number to r1
  4185 00004DCD B201                <1> 	mov	dl, 1 ; owner flag mask
  4186 00004DCF E8CE050000          <1> 	call	access	
  4187                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4188 00004DD4 50                  <1> 	push	eax ; ** ; 24/12/2021
  4189                              <1> 		; mov r1,-(sp) / put i-number on stack
  4190 00004DD5 66B82800            <1> 	mov	ax, 40
  4191                              <1> 		; mov $40.,r1 / r1 = 40
  4192                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4193 00004DD9 6640                <1> 	inc	ax
  4194                              <1> 		; inc r1 / r1 = r1 + 1
  4195 00004DDB E88F060000          <1> 	call	imap
  4196                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4197                              <1> 			    ; /	inode map in r2 & m
  4198                              <1>           ; DX (MQ) has a 1 in the calculated bit position
  4199                              <1>           ; eBX (R2) has byte address of the byte with allocation bit
  4200                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4201                              <1> 	;	       Inode count must be checked here
  4202                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4203 00004DE0 8413                <1> 	test	[ebx], dl
  4204                              <1> 		; bitb mq,(r2) / is the i-node active
  4205 00004DE2 75F5                <1> 	jnz	short maknod1
  4206                              <1> 		; bne 1b / yes, try the next one
  4207 00004DE4 0813                <1> 	or	[ebx], dl
  4208                              <1> 		; bisb mq,(r2) / no, make it active 
  4209                              <1> 			     ; / (put a 1 in the bit map)
  4210 00004DE6 E8E1040000          <1> 	call	iget
  4211                              <1> 		; jsr r0,iget / get i-node into core
  4212 00004DEB 66F705[D66C0000]00- <1> 	test	word [i.flgs], 8000h 
  4212 00004DF3 80                  <1>
  4213                              <1> 		; tst i.flgs / is i-node already allocated
  4214 00004DF4 75E3                <1> 	jnz	short maknod1	
  4215                              <1> 		; blt 1b / yes, look for another one
  4216 00004DF6 66A3[3A700000]      <1> 	mov	[u.dirbuf], ax
  4217                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4218 00004DFC 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4219                              <1> 		; mov (sp)+,r1 / get current i-number back
  4220 00004DFD E8CA040000          <1> 	call	iget
  4221                              <1> 		; jsr r0,iget / get i-node in core
  4222 00004E02 E8A7F7FFFF          <1> 	call	mkdir
  4223                              <1> 		; jsr r0,mkdir / make a directory entry 
  4224                              <1> 			     ; / in current directory
  4225 00004E07 66A1[3A700000]      <1> 	mov	ax, [u.dirbuf]
  4226                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4227 00004E0D E8BA040000          <1> 	call	iget
  4228                              <1> 		; jsr r0,iget / get it into core
  4229                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4230 00004E12 B908000000          <1> 	mov	ecx, 8 
  4231 00004E17 31C0                <1> 	xor	eax, eax ; 0
  4232 00004E19 BF[D66C0000]        <1> 	mov	edi, inode 
  4233 00004E1E F3AB                <1> 	rep	stosd
  4234                              <1> 	;
  4235 00004E20 668F05[D66C0000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4236                              <1> 		; mov (sp)+,i.flgs / fill flags
  4237 00004E27 8A0D[54700000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4238 00004E2D 880D[D96C0000]      <1> 	mov 	[i.uid], cl
  4239                              <1> 		; movb u.uid,i.uid / user id	
  4240 00004E33 C605[D86C0000]01    <1> 	mov     byte [i.nlks], 1
  4241                              <1> 		; movb $1,i.nlks / 1 link
  4242                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4243                              <1> 	;mov	eax, [s.time]
  4244                              <1> 	;mov 	[i.ctim], eax
  4245                              <1> 	 	; mov s.time,i.ctim / time created
  4246                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4247                              <1> 	; Retro UNIX 8086 v1 modification !
  4248                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4249                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4250                              <1> 	;call	setimod
  4251                              <1> 	;	; jsr r0,setimod / set modified flag
  4252                              <1> 	;retn
  4253                              <1> 	;	; rts r0 / return
  4254                              <1> 	; 24/12/2021
  4255 00004E3A E999050000          <1> 	jmp	setimod
  4256                              <1> 
  4257                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4258                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4259                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4260                              <1> 	;
  4261                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4262                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4263                              <1> 	; The file descriptor refers to a file open for reading or
  4264                              <1> 	; writing. The read (or write) pointer is set as follows:
  4265                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4266                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4267                              <1> 	;	  current location plus offset.
  4268                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4269                              <1> 	;	  size of file plus offset.
  4270                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4271                              <1> 	;
  4272                              <1> 	; Calling sequence:
  4273                              <1> 	;	sysseek; offset; ptrname
  4274                              <1> 	; Arguments:
  4275                              <1> 	;	offset - number of bytes desired to move 
  4276                              <1> 	;		 the r/w pointer
  4277                              <1> 	;	ptrname - a switch indicated above
  4278                              <1> 	;
  4279                              <1> 	; Inputs: r0 - file descriptor 
  4280                              <1> 	; Outputs: -
  4281                              <1> 	; ...............................................................
  4282                              <1> 	;	
  4283                              <1> 	; Retro UNIX 8086 v1 modification: 
  4284                              <1> 	;       'sysseek' system call has three arguments; so,
  4285                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4286                              <1> 	;	* 2nd argument, offset is in CX register
  4287                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4288                              <1> 	;	
  4289                              <1> 
  4290 00004E3F E822000000          <1> 	call	seektell
  4291                              <1> 	; AX = u.count
  4292                              <1> 	; BX = *u.fofp
  4293                              <1> 		; jsr r0,seektell / get proper value in u.count
  4294                              <1> 		; add u.base,u.count / add u.base to it
  4295 00004E44 0305[28700000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4296 00004E4A 8903                <1> 	mov	[ebx], eax
  4297                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4298 00004E4C E954EEFFFF          <1> 	jmp	sysret
  4299                              <1> 		; br sysret4
  4300                              <1> 
  4301                              <1> systell: ; / get the r/w pointer
  4302                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4303                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4304                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4305                              <1> 	;
  4306                              <1> 	; Retro UNIX 8086 v1 modification:
  4307                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4308                              <1> 	; 	    it returns with error !
  4309                              <1> 	; Inputs: r0 - file descriptor 
  4310                              <1> 	; Outputs: r0 - file r/w pointer
  4311                              <1> 
  4312                              <1> 	;xor	ecx, ecx ; 0
  4313                              <1> 	;mov	edx, 1 ; 05/08/2013
  4314                              <1> 	; 24/12/2021
  4315 00004E51 29D2                <1> 	sub	edx, edx
  4316 00004E53 FEC2                <1> 	inc	dl
  4317                              <1> 	; edx = 1
  4318                              <1> 	;call 	seektell
  4319 00004E55 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4320                              <1> 	;mov	ebx, [u.fofp]
  4321 00004E5A 8B03                <1> 	mov	eax, [ebx]
  4322 00004E5C A3[08700000]        <1> 	mov	[u.r0], eax
  4323 00004E61 E93FEEFFFF          <1> 	jmp	sysret
  4324                              <1> 
  4325                              <1> ; Original unix v1 'systell' system call:
  4326                              <1> 		; jsr r0,seektell
  4327                              <1> 		; br error4
  4328                              <1> 
  4329                              <1> seektell:
  4330                              <1> 	; 03/01/2016
  4331                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4332                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4333                              <1> 	;
  4334                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4335                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4336                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4337                              <1> 	; getf. The i-node is brought into core and then u.count
  4338                              <1> 	; is checked to see it is a 0, 1, or 2.
  4339                              <1> 	; If it is 0 - u.count stays the same
  4340                              <1> 	;          1 - u.count = offset (u.fofp)
  4341                              <1> 	;	   2 - u.count = i.size (size of file)
  4342                              <1> 	; 	 		
  4343                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4344                              <1> 	;	Argument 1, file descriptor is in BX;
  4345                              <1> 	;	Argument 2, offset is in CX;
  4346                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4347                              <1> 	;
  4348                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4349                              <1> 	; call 	arg
  4350                              <1> 	;
  4351                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4352                              <1> 	;
  4353 00004E66 890D[28700000]      <1> 	mov 	[u.base], ecx ; offset
  4354                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4355                              <1> seektell0:
  4356 00004E6C 8915[2C700000]      <1> 	mov 	[u.count], edx
  4357                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4358                              <1> 	; mov	ax, bx
  4359                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4360                              <1> 			     ; / (index in u.fp list)
  4361                              <1> 	; call	getf
  4362                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4363                              <1> 	; BX = file descriptor (file number)
  4364 00004E72 E849FCFFFF          <1> 	call	getf1
  4365 00004E77 6609C0              <1> 	or	ax, ax ; i-number of the file
  4366                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4367                              <1> 		             ; / put it on the stack
  4368                              <1> 	;jz	error
  4369                              <1> 		; beq error4 / if i-number is 0, not active so error
  4370 00004E7A 750F                <1> 	jnz	short seektell1
  4371 00004E7C C705[5D700000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4371 00004E84 0000                <1>
  4372 00004E86 E9FAEDFFFF          <1> 	jmp	error
  4373                              <1> seektell1:
  4374                              <1> 	;push	eax
  4375 00004E8B 80FC80              <1> 	cmp	ah, 80h
  4376 00004E8E 7203                <1> 	jb	short seektell2
  4377                              <1> 		; bgt .+4 / if its positive jump
  4378 00004E90 66F7D8              <1> 	neg	ax
  4379                              <1> 		; neg r1 / if not make it positive
  4380                              <1> seektell2:
  4381 00004E93 E834040000          <1> 	call	iget
  4382                              <1> 		; jsr r0,iget / get its i-node into core
  4383 00004E98 8B1D[18700000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4384 00004E9E 803D[2C700000]01    <1> 	cmp	byte [u.count], 1
  4385                              <1> 		; cmp u.count,$1 / is ptr name =1
  4386 00004EA5 7705                <1> 	ja	short seektell3
  4387                              <1> 		; blt 2f / no its zero
  4388 00004EA7 740A                <1> 	je	short seektell_4
  4389                              <1> 		; beq 1f / yes its 1
  4390 00004EA9 31C0                <1> 	xor	eax, eax
  4391                              <1> 	;jmp	short seektell_5
  4392 00004EAB C3                  <1> 	retn
  4393                              <1> seektell3:
  4394                              <1> 	; 03/01/2016
  4395                              <1> 	;movzx	eax, word [i.size]
  4396 00004EAC 66A1[DA6C0000]      <1>         mov   	ax, [i.size]
  4397                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4398                              <1>                                    ; / in file in u.count
  4399                              <1> 	;jmp	short seektell_5
  4400                              <1> 		; br 2f
  4401 00004EB2 C3                  <1> 	retn
  4402                              <1> seektell_4: ; 1: / ptrname =1
  4403                              <1> 	;mov	ebx, [u.fofp]
  4404 00004EB3 8B03                <1> 	mov	eax, [ebx]
  4405                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4406                              <1> ;seektell_5: ; 2: / ptrname =0
  4407                              <1> 	;mov	[u.count], eax
  4408                              <1> 	;pop	eax 
  4409                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4410 00004EB5 C3                  <1> 	retn
  4411                              <1> 		; rts r0
  4412                              <1> 
  4413                              <1> sysintr: ; / set interrupt handling
  4414                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4415                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4416                              <1> 	;
  4417                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4418                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4419                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4420                              <1> 	; If one does the interrupt character in the tty buffer is
  4421                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4422                              <1> 	; 'sysret' is just called.	
  4423                              <1> 	;
  4424                              <1> 	; Calling sequence:
  4425                              <1> 	;	sysintr; arg
  4426                              <1> 	; Argument:
  4427                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4428                              <1> 	;	    - if 1, intterupts cause their normal result
  4429                              <1> 	;		 i.e force an exit.
  4430                              <1> 	;	    - if arg is a location within the program,
  4431                              <1> 	;		control is passed to that location when
  4432                              <1> 	;		an interrupt occurs.	
  4433                              <1> 	; Inputs: -
  4434                              <1> 	; Outputs: -
  4435                              <1> 	; ...............................................................
  4436                              <1> 	;	
  4437                              <1> 	; Retro UNIX 8086 v1 modification: 
  4438                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4439                              <1> 	;	then branches into sysquit.
  4440                              <1> 	;
  4441 00004EB6 66891D[4C700000]    <1> 	mov	[u.intr], bx
  4442                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4443                              <1> 		; br 1f / go into quit routine
  4444 00004EBD E9E3EDFFFF          <1> 	jmp	sysret
  4445                              <1> 
  4446                              <1> sysquit:
  4447                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4448                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4449                              <1> 	;
  4450                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4451                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4452                              <1> 	; tty exists. If one does the interrupt character in the tty
  4453                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4454                              <1> 	; 'sysret' is just called.	
  4455                              <1> 	;
  4456                              <1> 	; Calling sequence:
  4457                              <1> 	;	sysquit; arg
  4458                              <1> 	; Argument:
  4459                              <1> 	;	arg - if 0, this call diables quit signals from the
  4460                              <1> 	;		typewriter (ASCII FS)
  4461                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4462                              <1> 	;		cease and a core image to be produced.
  4463                              <1> 	;		 i.e force an exit.
  4464                              <1> 	;	    - if arg is an addres in the program,
  4465                              <1> 	;		a quit causes control to sent to that
  4466                              <1> 	;		location.	
  4467                              <1> 	; Inputs: -
  4468                              <1> 	; Outputs: -
  4469                              <1> 	; ...............................................................
  4470                              <1> 	;	
  4471                              <1> 	; Retro UNIX 8086 v1 modification: 
  4472                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4473                              <1> 	;	then branches into 'sysret'.
  4474                              <1> 	;
  4475 00004EC2 66891D[4E700000]    <1> 	mov	[u.quit], bx
  4476 00004EC9 E9D7EDFFFF          <1> 	jmp	sysret
  4477                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4478                              <1> 	;1:
  4479                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4480                              <1> 			      ; / to r1
  4481                              <1> 		; beq sysret4 / return to user
  4482                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4483                              <1> 			   ; / in the tty buffer
  4484                              <1> 		; br sysret4 / return to user
  4485                              <1> 
  4486                              <1> syssetuid: ; / set process id
  4487                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4488                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4489                              <1> 	;
  4490                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4491                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4492                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4493                              <1> 	; Only the super user can make this call.	
  4494                              <1> 	;
  4495                              <1> 	; Calling sequence:
  4496                              <1> 	;	syssetuid
  4497                              <1> 	; Arguments: -
  4498                              <1> 	;
  4499                              <1> 	; Inputs: (u.r0) - contains the process id.
  4500                              <1> 	; Outputs: -
  4501                              <1> 	; ...............................................................
  4502                              <1> 	;	
  4503                              <1> 	; Retro UNIX 8086 v1 modification: 
  4504                              <1> 	;       BL contains the (new) user ID of the current process
  4505                              <1> 
  4506                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4507 00004ECE 3A1D[55700000]      <1> 	cmp	bl, [u.ruid] 
  4508                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4509                              <1> 			       ; / id number
  4510 00004ED4 741E                <1> 	je	short setuid1
  4511                              <1> 		; beq 1f / yes
  4512 00004ED6 803D[54700000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4513                              <1> 		; tstb u.uid / no, is current user the super user?
  4514                              <1> 	;ja	error
  4515                              <1> 		; bne error4 / no, error
  4516 00004EDD 760F                <1> 	jna	short setuid0
  4517 00004EDF C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4517 00004EE7 0000                <1>
  4518                              <1> 				;  'permission denied !' error
  4519 00004EE9 E997EDFFFF          <1> 	jmp	error
  4520                              <1> setuid0:
  4521 00004EEE 881D[55700000]      <1> 	mov	[u.ruid], bl
  4522                              <1> setuid1: ; 1:
  4523 00004EF4 881D[54700000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4524                              <1> 		; movb r1,u.uid / put process id in u.uid
  4525                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4526 00004EFA E9A6EDFFFF          <1> 	jmp	sysret
  4527                              <1> 		; br sysret4 / system return
  4528                              <1> 
  4529                              <1> sysgetuid: ; < get user id >
  4530                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4531                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4532                              <1> 	;
  4533                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4534                              <1> 	; The real user ID identifies the person who is logged in,
  4535                              <1> 	; in contradistinction to the effective user ID, which
  4536                              <1> 	; determines his access permission at each moment. It is thus
  4537                              <1> 	; useful to programs which operate using the 'set user ID'
  4538                              <1> 	; mode, to find out who invoked them.	
  4539                              <1> 	;
  4540                              <1> 	; Calling sequence:
  4541                              <1> 	;	syssetuid
  4542                              <1> 	; Arguments: -
  4543                              <1> 	;
  4544                              <1> 	; Inputs: -
  4545                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4546                              <1> 	; ...............................................................
  4547                              <1> 	;	
  4548                              <1> 	; Retro UNIX 8086 v1 modification: 
  4549                              <1> 	;       AL contains the real user ID at return.
  4550                              <1> 	;
  4551 00004EFF 0FB605[55700000]    <1> 	movzx 	eax, byte [u.ruid]
  4552 00004F06 A3[08700000]        <1> 	mov	[u.r0], eax
  4553                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4554 00004F0B E995EDFFFF          <1> 	jmp	sysret
  4555                              <1> 		; br sysret4 / systerm return, sysret
  4556                              <1> 
  4557                              <1> anyi: 
  4558                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4559                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4560                              <1> 	;
  4561                              <1> 	; 'anyi' is called if a file deleted while open.
  4562                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4563                              <1> 	;
  4564                              <1> 	; INPUTS ->
  4565                              <1> 	;    r1 - contains an i-number
  4566                              <1> 	;    fsp - start of table containing open files
  4567                              <1> 	;
  4568                              <1> 	; OUTPUTS ->
  4569                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4570                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4571                              <1> 	;    if file not found - bit in i-node map is cleared
  4572                              <1> 	;    			 (i-node is freed)
  4573                              <1> 	;               all blocks related to i-node are freed
  4574                              <1> 	;	        all flags in i-node are cleared
  4575                              <1> 	; ((AX = R1)) input
  4576                              <1> 	;
  4577                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4578                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4579                              <1> 	;
  4580                              <1> 		; / r1 contains an i-number
  4581 00004F10 BB[D66D0000]        <1> 	mov	ebx, fsp
  4582                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4583                              <1> anyi_1: ; 1:
  4584 00004F15 663B03              <1> 	cmp	ax, [ebx]
  4585                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4586 00004F18 7433                <1> 	je	short anyi_3
  4587                              <1> 		; beq 1f / yes, 1f
  4588 00004F1A 66F7D8              <1> 	neg	ax
  4589                              <1> 		; neg r1 / no complement r1
  4590 00004F1D 663B03              <1> 	cmp	ax, [ebx]
  4591                              <1> 		; cmp r1,(r2) / do they match now?
  4592 00004F20 742B                <1> 	je	short anyi_3
  4593                              <1> 		; beq 1f / yes, transfer
  4594                              <1> 		; / i-numbers do not match
  4595 00004F22 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4596                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4597                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4598 00004F25 81FB[CA6F0000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4599                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4600                              <1> 				; / are we at last entry in the table
  4601 00004F2B 72E8                <1> 	jb	short anyi_1
  4602                              <1> 		; blt 1b / no, check next entries i-number
  4603                              <1> 	;cmp	ax, 32768
  4604 00004F2D 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4605                              <1> 		; tst r1 / yes, no match
  4606                              <1> 		; bge .+4
  4607 00004F30 7203                <1> 	jb	short anyi_2
  4608 00004F32 66F7D8              <1> 	neg	ax
  4609                              <1> 		; neg r1 / make i-number positive
  4610                              <1> anyi_2:	
  4611 00004F35 E835050000          <1> 	call	imap
  4612                              <1> 		; jsr r0,imap / get address of allocation bit 
  4613                              <1> 			    ; / in the i-map in r2
  4614                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4615                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4616                              <1>  	; not	dx
  4617 00004F3A F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4618                              <1>         ;and	[ebx], dx
  4619 00004F3C 2013                <1> 	and 	[ebx], dl 
  4620                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4621 00004F3E E8B7040000          <1> 	call	itrunc
  4622                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4623 00004F43 66C705[D66C0000]00- <1>  	mov 	word [i.flgs], 0
  4623 00004F4B 00                  <1>
  4624                              <1> 		; clr i.flgs / clear all flags in the i-node
  4625 00004F4C C3                  <1> 	retn
  4626                              <1> 		;rts	r0 / return
  4627                              <1> anyi_3: ; 1: / i-numbers match
  4628 00004F4D FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4629                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4630                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4631 00004F50 C3                  <1> 	retn
  4632                              <1> 		; rts r0
  1995                                  %include 'u3.s'        ; 10/05/2015
  1996                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  1997                              <1> ; Last Modification: 24/12/2021
  1998                              <1> ; ----------------------------------------------------------------------------
  1999                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2000                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2001                              <1> ;
  2002                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2003                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2004                              <1> ; <Bell Laboratories (17/3/1972)>
  2005                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2006                              <1> ;
  2007                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2008                              <1> ;
  2009                              <1> ; ****************************************************************************
  2010                              <1> 
  2011                              <1> tswitch: ; Retro UNIX 386 v1
  2012                              <1> tswap:
  2013                              <1> 	; 01/09/2015
  2014                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2015                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2016                              <1> 	; time out swap, called when a user times out.
  2017                              <1> 	; the user is put on the low priority queue.
  2018                              <1> 	; This is done by making a link from the last user
  2019                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2020                              <1> 	; then he is swapped out.
  2021                              <1> 	;
  2022                              <1> 	; Retro UNIX 386 v1 modification ->
  2023                              <1> 	;       swap (software task switch) is performed by changing
  2024                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2025                              <1> 	;	as in Retro UNIX 8086 v1.
  2026                              <1> 	;
  2027                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2028                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2029                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2030                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2031                              <1> 	;	compatibles was using 1MB segmented memory 
  2032                              <1> 	;	in 8086/8088 times.
  2033                              <1> 	;
  2034                              <1> 	; INPUTS ->
  2035                              <1> 	;    u.uno - users process number
  2036                              <1> 	;    runq+4 - lowest priority queue
  2037                              <1> 	; OUTPUTS ->
  2038                              <1> 	;    r0 - users process number
  2039                              <1> 	;    r2 - lowest priority queue address
  2040                              <1> 	;
  2041                              <1> 	; ((AX = R0, BX = R2)) output
  2042                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2043                              <1> 	;
  2044 00004F51 A0[57700000]        <1> 	mov 	al, [u.uno]
  2045                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2046                              <1> 		; mov  $runq+4,r2 
  2047                              <1> 			; / move lowest priority queue address to r2
  2048 00004F56 E8CD000000          <1>         call 	putlu
  2049                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2050                              <1> 		             ; / u.uno's user
  2051                              <1> 
  2052                              <1> switch: ; Retro UNIX 386 v1
  2053                              <1> swap:
  2054                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2055                              <1> 	; 02/09/2015
  2056                              <1> 	; 01/09/2015
  2057                              <1> 	; 31/08/2015
  2058                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2059                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2060                              <1> 	; 'swap' is routine that controls the swapping of processes
  2061                              <1> 	; in and out of core.
  2062                              <1> 	;
  2063                              <1> 	; Retro UNIX 386 v1 modification ->
  2064                              <1> 	;       swap (software task switch) is performed by changing
  2065                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2066                              <1> 	;	as in Retro UNIX 8086 v1.
  2067                              <1> 	;
  2068                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2069                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2070                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2071                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2072                              <1> 	;	compatibles was using 1MB segmented memory 
  2073                              <1> 	;	in 8086/8088 times.
  2074                              <1> 	;
  2075                              <1> 	; INPUTS ->
  2076                              <1> 	;    runq table - contains processes to run.
  2077                              <1> 	;    p.link - contains next process in line to be run.
  2078                              <1> 	;    u.uno - process number of process in core	
  2079                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2080                              <1> 	; OUTPUTS ->
  2081                              <1> 	;    (original unix v1 -> present process to its disk block)
  2082                              <1> 	;    (original unix v1 -> new process into core -> 
  2083                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2084                              <1> 	;	   for new process)
  2085                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2086                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2087                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2088                              <1> 	;	 for now, it will swap the process if there is not
  2089                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2090                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2091                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2092                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2093                              <1> 	;
  2094                              <1> 	;    u.pri -points to highest priority run Q.
  2095                              <1> 	;    r2 - points to the run queue.
  2096                              <1> 	;    r1 - contains new process number
  2097                              <1> 	;    r0 - points to place in routine or process that called
  2098                              <1> 	;	  swap all user parameters
  2099                              <1> 	;				
  2100                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2101                              <1> 	;
  2102                              <1> swap_0:
  2103                              <1> 		;mov $300,*$ps / processor priority = 6
  2104 00004F5B BE[FA6F0000]        <1> 	mov	esi, runq
  2105                              <1> 		; mov $runq,r2 / r2 points to runq table
  2106                              <1> swap_1: ; 1: / search runq table for highest priority process
  2107 00004F60 668B06              <1> 	mov	ax, [esi]
  2108 00004F63 6621C0              <1> 	and 	ax, ax
  2109                              <1>        		; tst (r2)+ / are there any processes to run 
  2110                              <1> 			  ; / in this Q entry
  2111 00004F66 7507                <1> 	jnz	short swap_2
  2112                              <1>        		; bne 1f / yes, process 1f
  2113                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2114                              <1> 			       ; / to end of table
  2115                              <1> 		; bne 1b / if not at end, go back
  2116 00004F68 E8E0000000          <1> 	call	idle
  2117                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2118                              <1> 				       ; / all queues are empty
  2119 00004F6D EBF1                <1> 	jmp	short swap_1
  2120                              <1> 		; br swap
  2121                              <1> swap_2: ; 1:
  2122 00004F6F 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2123                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2124                              <1>  		; mov r2,u.pri / set present user to this run queue
  2125                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2126 00004F72 38E0                <1> 	cmp	al, ah
  2127                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2128                              <1> 			      ; / in this Q to be run
  2129 00004F74 740A                <1> 	je	short swap_3
  2130                              <1>        		; beq 1f / yes
  2131                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2132                              <1> 	;movzx	ebx, al
  2133 00004F76 8AA3[756D0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2134 00004F7C 8826                <1>        	mov	[esi], ah
  2135                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2136                              <1> 				       ; / in line into run queue
  2137 00004F7E EB05                <1> 	jmp	short swap_4
  2138                              <1>        		; br 2f
  2139                              <1> swap_3: ; 1:
  2140                              <1> 	;xor	dx, dx
  2141                              <1> 	; 24/12/2021
  2142 00004F80 31D2                <1> 	xor	edx, edx
  2143 00004F82 668916              <1> 	mov	[esi], dx
  2144                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2145                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2146                              <1>       ; / in new process if required
  2147                              <1>        		; clr *$ps / clear processor status
  2148 00004F85 8A25[57700000]      <1> 	mov 	ah, [u.uno]
  2149 00004F8B 38C4                <1> 	cmp	ah, al
  2150                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2151                              <1> 			      ; / the process in core?
  2152 00004F8D 743B                <1>        	je	short swap_8
  2153                              <1>        		; beq 2f / yes, don't have to swap
  2154                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2155                              <1> 			   ; / (address in routine that called swap)
  2156                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2157                              <1> 	; 01/09/2015
  2158                              <1> 	;mov	[u.usp], esp
  2159                              <1>        		; mov sp,u.usp / save stack pointer
  2160                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2161                              <1> 			       ; / to the stack pointer
  2162 00004F8F 08E4                <1> 	or	ah, ah
  2163                              <1>        		; tstb u.uno / is the process # = 0
  2164 00004F91 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2165                              <1> 		; beq  1f / yes, kill process by overwriting
  2166                              <1> 	; 02/09/2015
  2167 00004F93 8925[04700000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2168                              <1> 	;
  2169 00004F99 E834000000          <1> 	call	wswap
  2170                              <1> 		;jsr r0,wswap / write out core to disk
  2171                              <1> 	 ; 31/08/2015
  2172                              <1> 	;movzx	ebx, al ; New (running) process number
  2173 00004F9E EB1C                <1> 	jmp 	short swap_7
  2174                              <1> swap_6:
  2175                              <1> 	; 31/08/2015
  2176                              <1> 	; Deallocate memory pages belong to the process
  2177                              <1> 	; which is being terminated
  2178                              <1> 	; 14/05/2015 ('sysexit')
  2179                              <1>  	; Deallocate memory pages of the process
  2180                              <1> 	; (Retro UNIX 386 v1 modification !)
  2181                              <1> 	;
  2182                              <1> 	; movzx ebx, al
  2183 00004FA0 53                  <1> 	push	ebx
  2184 00004FA1 A1[61700000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2185 00004FA6 8B1D[65700000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2186 00004FAC E8B9E0FFFF          <1> 	call	deallocate_page_dir
  2187 00004FB1 A1[58700000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2188 00004FB6 E847E1FFFF          <1> 	call	deallocate_page
  2189 00004FBB 5B                  <1> 	pop	ebx
  2190                              <1> swap_7: ;1: 
  2191                              <1> 	; 02/09/2015
  2192                              <1> 	; 31/08/2015
  2193                              <1> 	; 14/05/2015
  2194 00004FBC C0E302              <1> 	shl	bl, 2 ; * 4 
  2195 00004FBF 8B83[926D0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2196                              <1> 	;cli
  2197 00004FC5 E831000000          <1> 	call	rswap
  2198                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2199                              <1> 		; jsr r0,rswap / read new process into core
  2200                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2201                              <1> 			      ; / to his program to its normal
  2202                              <1> 	; 01/09/2015
  2203                              <1> 	;mov	esp, [u.usp]	
  2204                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2205                              <1> 			     ; / new process stack
  2206                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2207                              <1> 			     ; / that just got swapped in, left off.,
  2208                              <1> 			     ; / i.e., transfer control to new process
  2209                              <1> 	;sti
  2210                              <1> swap_8: ;2:
  2211                              <1> 	; RETRO UNIX 8086 v1 modification !
  2212 00004FCA C605[4A700000]04    <1> 	mov	byte [u.quant], time_count 
  2213                              <1> 		; movb    $30.,uquant / initialize process time quantum
  2214 00004FD1 C3                  <1> 	retn
  2215                              <1> 		; rts r0 / return
  2216                              <1> 
  2217                              <1> wswap:  ; < swap out, swap to disk >
  2218                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2219                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2220                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2221                              <1> 	; appropriate disk area.
  2222                              <1> 	;
  2223                              <1> 	; Retro UNIX 386 v1 modification ->
  2224                              <1> 	;       User (u) structure content and the user's register content
  2225                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2226                              <1> 	;	saving 'u' structure and user registers for task switching).
  2227                              <1> 	;	u.usp - points to kernel stack address which contains
  2228                              <1> 	;		user's registers while entering system call.  
  2229                              <1> 	;	u.sp  - points to kernel stack address 
  2230                              <1> 	;		to return from system call -for IRET-.
  2231                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2232                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2233                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2234                              <1> 	;
  2235                              <1> 	; Retro UNIX 8086 v1 modification ->
  2236                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2237                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2238                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2239                              <1> 	;	compatibles was using 1MB segmented memory 
  2240                              <1> 	;	in 8086/8088 times.
  2241                              <1> 	;
  2242                              <1> 	; INPUTS ->
  2243                              <1> 	;    u.break - points to end of program
  2244                              <1> 	;    u.usp - stack pointer at the moment of swap
  2245                              <1> 	;    core - beginning of process program		
  2246                              <1> 	;    ecore - end of core 	
  2247                              <1> 	;    user - start of user parameter area		
  2248                              <1> 	;    u.uno - user process number	
  2249                              <1> 	;    p.dska - holds block number of process	
  2250                              <1> 	; OUTPUTS ->
  2251                              <1> 	;    swp I/O queue
  2252                              <1> 	;    p.break - negative word count of process 
  2253                              <1> 	;    r1 - process disk address	
  2254                              <1> 	;    r2 - negative word count
  2255                              <1> 	;
  2256                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2257                              <1> 	;
  2258                              <1> 	; INPUTS ->
  2259                              <1> 	;    u.uno - process number (to be swapped out)
  2260                              <1> 	; OUTPUTS ->
  2261                              <1> 	;    none
  2262                              <1> 	;
  2263                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2264                              <1> 	;
  2265 00004FD2 8B3D[58700000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2266 00004FD8 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2267 00004FDD BE[00700000]        <1> 	mov	esi, user ; active user (u) structure	
  2268 00004FE2 F3A5                <1> 	rep	movsd
  2269                              <1> 	;
  2270 00004FE4 8B35[04700000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2271                              <1> 			     ;      points to user registers)
  2272 00004FEA 8B0D[00700000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2273                              <1> 			     ; (for IRET)
  2274                              <1> 			     ; [u.sp] -> EIP (user)
  2275                              <1> 			     ; [u.sp+4]-> CS (user)
  2276                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2277                              <1> 			     ; [u.sp+12] -> ESP (user)
  2278                              <1> 			     ; [u.sp+16] -> SS (user)	
  2279 00004FF0 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2280 00004FF2 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2281                              <1> 			     ; (for IRET) 	
  2282 00004FF5 C1E902              <1> 	shr	ecx, 2	     		
  2283 00004FF8 F3A5                <1> 	rep	movsd
  2284 00004FFA C3                  <1> 	retn
  2285                              <1> 
  2286                              <1> 	; Original UNIX v1 'wswap' routine:
  2287                              <1> 	; wswap:
  2288                              <1> 		; mov *$30,u.emt / determines handling of emts
  2289                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2290                              <1> 				; / illegal instructions
  2291                              <1> 		; mov u.break,r2 / put process program break address in r2
  2292                              <1> 		; inc r2 / add 1 to it 
  2293                              <1> 		; bic $1,r2 / make it even
  2294                              <1> 		; mov r2,u.break / set break to an even location
  2295                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2296                              <1> 			     ; / at moment of swap in r3
  2297                              <1> 		; cmp r2,$core / is u.break less than $core
  2298                              <1> 		; blos 2f / yes
  2299                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2300                              <1>        		; bhis 2f / yes
  2301                              <1> 	; 1:
  2302                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2303                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2304                              <1> 		; bne 1b / no, keep packing
  2305                              <1> 	 	; br 1f / yes
  2306                              <1> 	; 2:
  2307                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2308                              <1> 	; 1:
  2309                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2310                              <1> 			   ; / (user up to end of stack gets written out)
  2311                              <1> 		; neg r2 / make it negative
  2312                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2313                              <1> 		; mov r2,swp+4 / word count
  2314                              <1> 		; movb u.uno,r1 / move user process number to r1
  2315                              <1> 		; asl r1 / x2 for index
  2316                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2317                              <1> 				     ; / into the p.break table
  2318                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2319                              <1> 				    ; /	for process to r1
  2320                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2321                              <1> 			     ; / (block number)
  2322                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2323                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2324                              <1> 	; 1:
  2325                              <1>        		; tstb swp+1 / is lt done writing?
  2326                              <1>        		; bne 1b / no, wait
  2327                              <1> 		; rts r0 / yes, return to swap
  2328                              <1> 
  2329                              <1> rswap:  ; < swap in, swap from disk >
  2330                              <1> 	; 15/09/2015
  2331                              <1> 	; 28/08/2015
  2332                              <1> 	; 14/05/2015
  2333                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2334                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2335                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2336                              <1> 	; from disk into core.
  2337                              <1> 	;
  2338                              <1> 	; Retro UNIX 386 v1 modification ->
  2339                              <1> 	;       User (u) structure content and the user's register content
  2340                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2341                              <1> 	;	saving 'u' structure and user registers for task switching).
  2342                              <1> 	;	u.usp - points to kernel stack address which contains
  2343                              <1> 	;		user's registers while entering system call.  
  2344                              <1> 	;	u.sp  - points to kernel stack address 
  2345                              <1> 	;		to return from system call -for IRET-.
  2346                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2347                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2348                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2349                              <1> 	;
  2350                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2351                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2352                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2353                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2354                              <1> 	;	compatibles was using 1MB segmented memory 
  2355                              <1> 	;	in 8086/8088 times.
  2356                              <1> 	;
  2357                              <1> 	; INPUTS ->
  2358                              <1> 	;    r1 - process number of process to be read in
  2359                              <1> 	;    p.break - negative of word count of process 
  2360                              <1> 	;    p.dska - disk address of the process		
  2361                              <1> 	;    u.emt - determines handling of emt's 	
  2362                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2363                              <1> 	; OUTPUTS ->
  2364                              <1> 	;    8 = (u.ilgins)
  2365                              <1> 	;    24 = (u.emt)
  2366                              <1> 	;    swp - bit 10 is set to indicate read 
  2367                              <1> 	;		(bit 15=0 when reading is done)	
  2368                              <1> 	;    swp+2 - disk block address
  2369                              <1> 	;    swp+4 - negative word count 	
  2370                              <1> 	;      ((swp+6 - address of user structure)) 
  2371                              <1> 	;
  2372                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2373                              <1> 	;
  2374                              <1> 	; INPUTS ->
  2375                              <1> 	;    AL	- new process number (to be swapped in)	 
  2376                              <1> 	; OUTPUTS ->
  2377                              <1> 	;    none
  2378                              <1> 	;
  2379                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2380                              <1> 	;
  2381                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2382 00004FFB 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2383 00004FFD B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2384 00005002 BF[00700000]        <1> 	mov	edi, user ; active user (u) structure	
  2385 00005007 F3A5                <1> 	rep	movsd
  2386 00005009 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2387 0000500A 8B3D[04700000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2388                              <1> 			     ;      points to user registers)
  2389 00005010 8B0D[00700000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2390                              <1> 			     ; (for IRET)
  2391                              <1> 			     ; [u.sp] -> EIP (user)
  2392                              <1> 			     ; [u.sp+4]-> CS (user)
  2393                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2394                              <1> 			     ; [u.sp+12] -> ESP (user)
  2395                              <1> 			     ; [u.sp+16] -> SS (user)		
  2396                              <1> 	; 28/08/2015
  2397 00005016 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2398 00005018 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2399                              <1> 			     ; (for IRET) 	
  2400 0000501B C1E902              <1> 	shr	ecx, 2	       		
  2401 0000501E F3A5                <1> 	rep	movsd
  2402 00005020 8B25[04700000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2403 00005026 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2404 00005027 C3                  <1> 	retn
  2405                              <1> 
  2406                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2407                              <1> 	;rswap:
  2408                              <1>        		; asl r1 / process number x2 for index
  2409                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2410                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2411                              <1>        		; bis $2000,swp / read
  2412                              <1>        		; jsr r0,ppoke / read it in 
  2413                              <1> 	; 1:
  2414                              <1>        		; tstb swp+1 / done
  2415                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2416                              <1>        		; mov u.emt,*$30 / yes move these
  2417                              <1>        		; mov u.ilgins,*$10 / back
  2418                              <1>        		; rts r0 / return
  2419                              <1> 
  2420                              <1> 	;unpack: ; / move stack back to its normal place
  2421                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2422                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2423                              <1> 		; blos 2f / yes, return
  2424                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2425                              <1> 			     ; / before swapping
  2426                              <1> 		; bhis 2f / yes, return
  2427                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2428                              <1> 		; add r3,r2
  2429                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2430                              <1> 	; 1:
  2431                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2432                              <1> 		; cmp r2,u.break / in core
  2433                              <1> 		; bne 1b
  2434                              <1> 	; 2:
  2435                              <1>        		; rts r0
  2436                              <1> 
  2437                              <1> putlu: 
  2438                              <1> 	; 12/09/2015
  2439                              <1> 	; 02/09/2015
  2440                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2441                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2442                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2443                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2444                              <1> 	; the last process on the queue to process in r1 by putting
  2445                              <1> 	; the process number in r1 into the last process's link.
  2446                              <1> 	;
  2447                              <1> 	; INPUTS ->
  2448                              <1> 	;    r1 - user process number
  2449                              <1> 	;    r2 - points to lowest priority queue 
  2450                              <1> 	;    p.dska - disk address of the process		
  2451                              <1> 	;    u.emt - determines handling of emt's 	
  2452                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2453                              <1> 	; OUTPUTS ->
  2454                              <1> 	;    r3 - process number of last process on the queue upon
  2455                              <1> 	;	  entering putlu
  2456                              <1> 	;    p.link-1 + r3 - process number in r1
  2457                              <1> 	;    r2 - points to lowest priority queue
  2458                              <1> 	;
  2459                              <1> 	; ((Modified registers: EDX, EBX)) 
  2460                              <1> 	;
  2461                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2462                              <1> 
  2463                              <1> 	; eBX = r2
  2464                              <1> 	; eAX = r1 (AL=r1b)
  2465                              <1> 
  2466 00005028 BB[FA6F0000]        <1> 	mov	ebx, runq
  2467 0000502D 0FB613              <1> 	movzx  	edx, byte [ebx]
  2468 00005030 43                  <1> 	inc	ebx
  2469 00005031 20D2                <1> 	and	dl, dl
  2470                              <1> 		; tstb (r2)+ / is queue empty?
  2471 00005033 740A                <1>        	jz	short putlu_1
  2472                              <1> 		; beq 1f / yes, branch
  2473 00005035 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2474                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2475                              <1> 			     ; / in r3
  2476 00005037 8882[756D0000]      <1>        	mov	[edx+p.link-1], al
  2477                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2478                              <1> 			     ; / "last users" link
  2479 0000503D EB03                <1> 	jmp	short putlu_2
  2480                              <1> 		; br 2f /
  2481                              <1> putlu_1: ; 1:
  2482 0000503F 8843FF              <1> 	mov	[ebx-1], al
  2483                              <1>        		; movb r1,-1(r2) / user is only user; 
  2484                              <1> 			    ; / put process no. at beginning and at end
  2485                              <1> putlu_2: ; 2: 
  2486 00005042 8803                <1> 	mov	[ebx], al
  2487                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2488                              <1> 			     ; / on the queue
  2489 00005044 88C2                <1> 	mov	dl, al
  2490 00005046 88B2[756D0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2491                              <1> 		; dec r2 / restore r2
  2492 0000504C C3                  <1>         retn
  2493                              <1> 		; rts r0
  2494                              <1> 
  2495                              <1> ;copyz:
  2496                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2497                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2498                              <1> ;       mov     (r0)+,r1
  2499                              <1> ;       mov     (r0)+,r2
  2500                              <1> ;1:
  2501                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2502                              <1> ;       cmp     r1,r2 
  2503                              <1> ;       blo     1b
  2504                              <1> ;       mov     (sp)+,r2 / restore r2
  2505                              <1> ;       mov     (sp)+,r1 / restore r1
  2506                              <1> ;       rts     r0 
  2507                              <1> 
  2508                              <1> idle:
  2509                              <1> 	; 01/09/2015
  2510                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2511                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2512                              <1> 	; (idle & wait loop)
  2513                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2514                              <1> 	; idle procedure!
  2515                              <1>       	;
  2516                              <1>   	; 01/09/2015
  2517 0000504D FB                  <1> 	sti
  2518                              <1>       	; 29/07/2013
  2519 0000504E F4                  <1>       	hlt
  2520 0000504F 90                  <1>       	nop ; 10/10/2013
  2521 00005050 90                  <1>       	nop
  2522 00005051 90                  <1>       	nop
  2523                              <1>       	; 23/10/2013
  2524 00005052 90                  <1>       	nop
  2525 00005053 90                  <1>       	nop
  2526 00005054 90                  <1>       	nop
  2527 00005055 90                  <1>       	nop
  2528 00005056 C3                  <1>       	retn      
  2529                              <1> 
  2530                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2531                              <1> 	;clr *$ps / clear ps
  2532                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2533                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2534                              <1> 	;1 / wait for interrupt
  2535                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2536                              <1> 	;mov (sp)+,*$ps
  2537                              <1> 	;rts r0
  2538                              <1> 
  2539                              <1> clear:
  2540                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2541                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2542                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2543                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2544                              <1> 	; on the current device (cdev)
  2545                              <1> 	;	
  2546                              <1> 	; INPUTS ->
  2547                              <1> 	;    r1 - block number of block to be zeroed
  2548                              <1> 	;    cdev - current device number 
  2549                              <1> 	; OUTPUTS ->
  2550                              <1> 	;    a zeroed I/O buffer onto the current device
  2551                              <1> 	;    r1 - points to last entry in the I/O buffer
  2552                              <1> 	;
  2553                              <1> 	; ((AX = R1)) input/output
  2554                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2555                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2556                              <1> 
  2557 00005057 E8890D0000          <1> 	call 	wslot
  2558                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2559                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2560 0000505C 89DF                <1> 	mov	edi, ebx ; r5
  2561 0000505E 89C2                <1> 	mov	edx, eax
  2562 00005060 B980000000          <1> 	mov	ecx, 128
  2563                              <1> 		; mov $256.,r3
  2564 00005065 31C0                <1> 	xor	eax, eax
  2565 00005067 F3AB                <1> 	rep	stosd
  2566 00005069 89D0                <1> 	mov	eax, edx
  2567                              <1> ; 1: 
  2568                              <1>        		; clr (r5)+ / zero data word in buffer
  2569                              <1>        		; dec r3
  2570                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2571                              <1> 	;call	dskwr
  2572                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2573                              <1>                              ; / block specified in r1
  2574                              <1> 	; eAX (r1) = block number
  2575                              <1> 	;retn
  2576                              <1> 		; rts r0
  2577                              <1> 	; 24/12/2021
  2578 0000506B E9910D0000          <1> 	jmp	dskwr
  1996                                  %include 'u4.s'        ; 15/04/2015
  1997                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  1998                              <1> ; Last Modification: 14/10/2015
  1999                              <1> ; ----------------------------------------------------------------------------
  2000                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2001                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2002                              <1> ;
  2003                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2004                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2005                              <1> ; <Bell Laboratories (17/3/1972)>
  2006                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2007                              <1> ;
  2008                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2009                              <1> ;
  2010                              <1> ; ****************************************************************************
  2011                              <1> 
  2012                              <1> ;setisp:
  2013                              <1>        ;mov     r1,-(sp)
  2014                              <1>        ;mov     r2,-(sp)
  2015                              <1>        ;mov     r3,-(sp)
  2016                              <1>        ;mov     clockp,-(sp)
  2017                              <1>        ;mov     $s.syst+2,clockp
  2018                              <1>        ;jmp     (r0)
  2019                              <1> 
  2020                              <1> clock: ; / interrupt from 60 cycle clock
  2021                              <1> 	
  2022                              <1> 	; 14/10/2015
  2023                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2024                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2025                              <1> 
  2026                              <1>        ;mov     r0,-(sp) / save r0
  2027                              <1>        ;tst     *$lks / restart clock?
  2028                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2029                              <1>        ;inc     (r0)
  2030                              <1>        ;bne     1f
  2031                              <1>        ;inc     -(r0)
  2032                              <1> ;1:
  2033                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2034                              <1>        ;inc     (r0)
  2035                              <1>        ;bne     1f
  2036                              <1>        ;inc     -(r0)
  2037                              <1> ;1:
  2038                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2039                              <1> 
  2040 00005070 803D[4A700000]00    <1> 	cmp	byte [u.quant], 0
  2041 00005077 772C                <1> 	ja	short clk_1
  2042                              <1> 	;
  2043 00005079 803D[FF6F0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2044 00005080 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2045 00005082 803D[57700000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2046 00005089 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2047 0000508B 66833D[4C700000]00  <1> 	cmp	word [u.intr], 0
  2048 00005093 7616                <1> 	jna	short clk_2
  2049                              <1> clk_0:
  2050                              <1> 	; 14/10/2015
  2051 00005095 FE05[FF6F0000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2052 0000509B 58                  <1> 	pop	eax ; return address to the timer interrupt
  2053                              <1> 	;
  2054 0000509C B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2055                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2056 0000509E E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2057                              <1> 	;
  2058 000050A0 E965ECFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2059                              <1> clk_1:
  2060 000050A5 FE0D[4A700000]      <1> 	dec	byte [u.quant]
  2061                              <1> clk_2:
  2062 000050AB C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2063                              <1> 
  2064                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2065                              <1> 
  2066                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2067                              <1>        ;decb    (r0)
  2068                              <1>        ;bge     1f / if less than 0
  2069                              <1>        ;clrb    (r0) / make it 0
  2070                              <1> ;1: / decrement time out counts return now if priority was not 0
  2071                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2072                              <1>        ;bge     2f / yes, check time outs
  2073                              <1>        ;tstb    (r0) / no, user timed out?
  2074                              <1>        ;bne     1f / no
  2075                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2076                              <1>        ;bne     1f / no, 1f
  2077                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2078                              <1>        ;sys     0 / sysrele
  2079                              <1>        ;rti
  2080                              <1> ;2: / priority is high so just decrement time out counts
  2081                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2082                              <1> ;2:
  2083                              <1>        ;tstb    (r0) / is the time out?
  2084                              <1>        ;beq     3f / yes, 3f (get next entry)
  2085                              <1>        ;decb    (r0) / no, decrement the time
  2086                              <1>        ;bne     3f / isit zero now?
  2087                              <1>        ;incb    (r0) / yes, increment the time
  2088                              <1> ;3:
  2089                              <1>        ;inc     r0 / next entry
  2090                              <1>        ;cmp     r0,$touts / end of toutt table?
  2091                              <1>        ;blo     2b / no, check this entry
  2092                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2093                              <1>        ;rti / return from interrupt
  2094                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2095                              <1>        ;mov     (sp)+,r0 / restore r0
  2096                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2097                              <1>        ;jsr     r0,setisp / save registers
  2098                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2099                              <1>                                ;  / the table
  2100                              <1> ;1:
  2101                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2102                              <1>        ;beq     2f / yes
  2103                              <1>        ;decb    toutt(r0) / no, decrement the time
  2104                              <1>        ;bne     2f / is the time 0, now
  2105                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2106                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2107                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2108                              <1> ;2:
  2109                              <1>        ;dec     r0 / set up r0 for next entry
  2110                              <1>        ;bge     1b / finished? , no, go back
  2111                              <1>        ;br      retisp / yes, restore registers and do a rti
  2112                              <1> 
  2113                              <1> ;retisp:
  2114                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2115                              <1>        ;mov     (sp)+,r3
  2116                              <1>        ;mov     (sp)+,r2
  2117                              <1>        ;mov     (sp)+,r1
  2118                              <1>        ;mov     (sp)+,r0
  2119                              <1>        ;rti     / return from interrupt
  2120                              <1> 
  2121                              <1> 
  2122                              <1> wakeup: ; / wakeup processes waiting for an event 
  2123                              <1> 	; / by linking them to the queue
  2124                              <1> 	;
  2125                              <1> 	; 15/09/2015
  2126                              <1> 	; 29/06/2015
  2127                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2128                              <1> 	;
  2129                              <1> 	; 15/05/2013 - 02/06/2014
  2130                              <1> 	; Retro UNIX 8086 v1 modification !
  2131                              <1> 	; (Process/task switching routine by using
  2132                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2133                              <1> 	;
  2134                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2135                              <1> 	; sleeping in the specified wait channel by creating a link 
  2136                              <1> 	; to it from the last user process on the run queue.
  2137                              <1> 	; If there is no process to wake up, nothing happens.
  2138                              <1> 	;
  2139                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2140                              <1> 	; 'switching' status of the current process (owns current tty)
  2141                              <1> 	; (via alt + function keys) to a process which has highest
  2142                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2143                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2144                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2145                              <1> 	; tty for tty switching by keyboard.)	 
  2146                              <1> 	; 
  2147                              <1> 	; INPUT -> 
  2148                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2149                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2150                              <1> 	;
  2151                              <1> 	; ((modified registers: EAX, EBX))
  2152                              <1> 	;
  2153 000050AC 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2154 000050AF 81C3[886C0000]      <1> 	add	ebx, wlist
  2155 000050B5 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2156 000050B7 20C0                <1> 	and	al, al
  2157 000050B9 7424                <1> 	jz	short wa0 ; nothing to wakeup
  2158                              <1> 	;
  2159 000050BB 30E4                <1> 	xor	ah, ah
  2160 000050BD 8825[4A700000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2161 000050C3 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2162                              <1> 	; 15/09/2015
  2163 000050C5 0FB6D8              <1> 	movzx	ebx, al
  2164 000050C8 88A3[656D0000]      <1> 	mov	[ebx+p.waitc-1], ah ; 0
  2165 000050CE FEC4                <1> 	inc	ah
  2166 000050D0 88A3[856D0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2167                              <1> 	;
  2168 000050D6 57                  <1> 	push	edi
  2169 000050D7 52                  <1> 	push	edx
  2170 000050D8 E84BFFFFFF          <1> 	call	putlu
  2171 000050DD 5A                  <1> 	pop	edx
  2172 000050DE 5F                  <1> 	pop	edi
  2173                              <1> wa0:
  2174 000050DF C3                  <1> 	retn
  2175                              <1> 
  2176                              <1> sleep: 
  2177                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2178                              <1> 	; 15/09/2015
  2179                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2180                              <1> 	;
  2181                              <1> 	; 09/05/2013 - 20/03/2014
  2182                              <1> 	;
  2183                              <1> 	; Retro UNIX 8086 v1 modification !
  2184                              <1> 	; (Process/task switching and quit routine by using
  2185                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2186                              <1> 	;
  2187                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2188                              <1> 	; tty and tape output or input becomes available
  2189                              <1> 	; and process is put on waiting channel and swapped out,
  2190                              <1> 	; then -when the tty or tape is ready to write or read-
  2191                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2192                              <1> 	;
  2193                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2194                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2195                              <1> 	; status of the current process also INT 1Ch will count down
  2196                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2197                              <1> 	; to tty buffer of the current process and kernel will get
  2198                              <1> 	; user input by using tty buffer of the current process
  2199                              <1> 	; (instead of standard INT 16h interrupt).
  2200                              <1> 	; TTY output will be redirected to related video page of text mode
  2201                              <1> 	; (INT 10h will be called with different video page depending
  2202                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2203                              <1> 	; pseudo screens.)
  2204                              <1> 	;
  2205                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2206                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2207                              <1> 	; characters/data on serial port(s).
  2208                              <1> 	;
  2209                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2210                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2211                              <1> 	; 
  2212                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2213                              <1> 	;
  2214                              <1> 	;; 05/10/2013
  2215                              <1>         ;10/12/2013
  2216                              <1> 	;cmp   byte [u.uno], 1
  2217                              <1>         ;ja    short sleep0
  2218                              <1> 	;retn
  2219                              <1> 
  2220                              <1> 	; 20/03/2014
  2221                              <1> 	;mov	bx, [runq]
  2222                              <1> 	;cmp	bl, bh
  2223                              <1> 	;jne	short sleep0	
  2224                              <1> 	; 25/02/2014
  2225                              <1> 	;cmp word ptr [runq], 0
  2226                              <1> 	;ja short sleep0	
  2227                              <1> 	;retn
  2228                              <1> sleep0:
  2229                              <1> 	;
  2230 000050E0 E851000000          <1> 	call	isintr
  2231                              <1> 	;jnz	sysret
  2232                              <1> 		; / wait for event
  2233                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2234                              <1> 			      ; / or quit from user
  2235                              <1>                		; br 2f / something happened
  2236                              <1> 			      ; / yes, his interrupt so return
  2237                              <1>                      	      ;	/ to user
  2238                              <1> 	; 2412/2021
  2239 000050E5 7405                <1> 	jz	short sleep_2
  2240                              <1> sleep_3:
  2241 000050E7 E9B9EBFFFF          <1> 	jmp	sysret
  2242                              <1> sleep_2:
  2243                              <1> 	; 30/06/2015
  2244 000050EC 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2245 000050EF 81C3[886C0000]      <1> 	add	ebx, wlist
  2246 000050F5 8A03                <1> 	mov	al, [ebx]
  2247 000050F7 20C0                <1> 	and	al, al
  2248 000050F9 7407                <1> 	jz	short sleep1
  2249 000050FB 53                  <1> 	push	ebx
  2250 000050FC E827FFFFFF          <1> 	call	putlu
  2251 00005101 5B                  <1> 	pop	ebx
  2252                              <1> sleep1:
  2253 00005102 A0[57700000]        <1> 	mov	al, [u.uno]    
  2254 00005107 8803                <1>   	mov	[ebx], al 	; put the process number
  2255                              <1> 				; in the wait channel
  2256                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2257                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2258                              <1> 				     ; / on the stack
  2259                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2260                              <1> 				     ; / to put to sleep in there
  2261                              <1>         ; 15/09/2015
  2262 00005109 0FB6D8              <1> 	movzx	ebx, al
  2263 0000510C C683[856D0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2264 00005113 FEC4                <1> 	inc	ah
  2265 00005115 88A3[656D0000]      <1> 	mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2266                              <1> 	;
  2267 0000511B 66FF35[EE6F0000]    <1> 	push    word [cdev]
  2268                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2269 00005122 E834FEFFFF          <1> 	call	swap
  2270                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2271 00005127 668F05[EE6F0000]    <1>         pop     word [cdev]
  2272                              <1> 		; mov (sp)+,cdev / restore device
  2273 0000512E E803000000          <1> 	call	isintr
  2274                              <1> 	; 22/09/2013
  2275                              <1> 	;jnz	sysret         
  2276                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2277                              <1>                		; br 2f / yes, return to new user
  2278                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2279                              <1> 				; / originally on the wait channel
  2280                              <1>        		; beq 1f / if 0 branch
  2281                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2282                              <1>        		; mov $300,*$ps / processor priority = 6
  2283                              <1> 		; jsr r0,putlu / create link to old process number
  2284                              <1>        		; clr *$ps / clear the status; process priority = 0
  2285                              <1> 	; 24/12/2021
  2286 00005133 75B2                <1> 	jnz	short sleep_3 ; jump to sysret
  2287                              <1>      ;1:
  2288 00005135 C3                  <1> 	retn
  2289                              <1> 		; rts r0 / return
  2290                              <1>      ;2:
  2291                              <1>         ;;jmp	sysret
  2292                              <1> 		; jmp sysret / return to user
  2293                              <1> 
  2294                              <1> isintr:
  2295                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2296                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2297                              <1> 	;
  2298                              <1> 	; 09/05/2013 - 30/05/2014
  2299                              <1> 	;
  2300                              <1> 	; Retro UNIX 8086 v1 modification !
  2301                              <1> 	; (Process/task switching and quit routine by using
  2302                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2303                              <1> 	;
  2304                              <1> 	; Retro UNIX 8086 v1 modification:
  2305                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2306                              <1> 	;  and there is a 'quit' request by user;
  2307                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2308                              <1> 	;  "nothing to do". (20/10/2013)
  2309                              <1> 	;
  2310                              <1> 	; 20/10/2013
  2311 00005136 66833D[38700000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2312 0000513E 761F                <1> 	jna	short isintr2 ; retn
  2313                              <1> 	; 03/09/2013
  2314                              <1> 	; (nothing to do)
  2315                              <1> 	;retn
  2316                              <1> 	; 22/09/2013
  2317 00005140 66833D[4C700000]00  <1> 	cmp	word [u.intr], 0
  2318 00005148 7615                <1> 	jna	short isintr2 ; retn
  2319                              <1> 	; 30/05/2014
  2320                              <1> 	;push	ax
  2321                              <1> 	; 24/12/2021
  2322 0000514A 50                  <1> 	push	eax
  2323 0000514B 66A1[4E700000]      <1> 	mov	ax, [u.quit]
  2324 00005151 6609C0              <1> 	or	ax, ax ; 0 ?
  2325 00005154 7408                <1> 	jz	short isintr1 ; zf = 1
  2326 00005156 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2327 0000515A 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2328                              <1> 	;xor	ax, ax ; zf = 1
  2329                              <1> 	; 24/12/2021
  2330 0000515C 31C0                <1> 	xor	eax, eax ; zf = 1
  2331                              <1> isintr1:
  2332                              <1> 	;pop	ax
  2333                              <1> 	 ; 24/12/2021
  2334 0000515E 58                  <1> 	pop	eax
  2335                              <1> isintr2: ; 22/09/2013
  2336                              <1> 	; zf=1 -> nothing to do
  2337 0000515F C3                  <1> 	retn
  2338                              <1> 
  2339                              <1> 	; UNIX v1 original 'isintr' routine... 
  2340                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2341                              <1>        	;mov     r2,-(sp) / save r2
  2342                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2343                              <1>         ;                 / typewriter
  2344                              <1>        	;beq     1f / if 0, do nothing except skip return
  2345                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2346                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2347                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2348                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2349                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2350                              <1>         ;              / of interrupts
  2351                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2352                              <1>      ;1:
  2353                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2354                              <1>      ;4:
  2355                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2356                              <1>        	;mov     (sp)+,r1
  2357                              <1>        	;rts     r0
  2358                              <1>      ;3: / interrupt char = quit (fs)
  2359                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2360                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2361                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2362                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2363                              <1>      ;1: / find process control tty entry in tty block
  2364                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2365                              <1>        	;beq     1f / block found go to 1f
  2366                              <1>        	;add     $8,r1 / look at next tty block
  2367                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2368                              <1>        	;blo     1b / no
  2369                              <1>        	;br      4b / no process control tty found so go to 4b
  2370                              <1>      ;1:
  2371                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2372                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2373                              <1>         ;                  / identifier
  2374                              <1>        	;inc     0f / increment
  2375                              <1>      ;1:
  2376                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2377                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2378                              <1>         ;             / being typed out after you hit the interrupt
  2379                              <1>         ;             / key
  2380                              <1>        	;br      1b
  1997                                  %include 'u5.s'        ; 03/06/2015
  1998                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS5.INC
  1999                              <1> ; Last Modification: 24/12/2021
  2000                              <1> ; ----------------------------------------------------------------------------
  2001                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2002                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2003                              <1> ;
  2004                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2005                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2006                              <1> ; <Bell Laboratories (17/3/1972)>
  2007                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2008                              <1> ;
  2009                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2010                              <1> ;
  2011                              <1> ; ****************************************************************************
  2012                              <1> 
  2013                              <1> mget:
  2014                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2015                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2016                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2017                              <1> 	;
  2018                              <1> 	; Get existing or (allocate) a new disk block for file
  2019                              <1> 	; 
  2020                              <1> 	; INPUTS ->
  2021                              <1> 	;    u.fofp (file offset pointer)
  2022                              <1> 	;    inode 
  2023                              <1> 	;    u.off (file offset)
  2024                              <1> 	; OUTPUTS ->
  2025                              <1> 	;    r1 (physical block number)
  2026                              <1> 	;    r2, r3, r5 (internal)
  2027                              <1> 	;
  2028                              <1> 	; ((AX = R1)) output
  2029                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2030                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2031                              <1> 
  2032                              <1> 		; mov *u.fofp,mq / file offset in mq
  2033                              <1> 		; clr ac / later to be high sig
  2034                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2035                              <1> 		; mov mq,r2
  2036                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2037                              <1> 		; bne 4f / branch for large file
  2038                              <1> mget_0:	
  2039 00005160 8B35[18700000]      <1>         mov     esi, [u.fofp]
  2040 00005166 0FB65E01            <1>         movzx   ebx, byte [esi+1]
  2041                              <1>         ; BX = r2
  2042                              <1>         ; 24/12/2021
  2043 0000516A F605[D76C0000]10    <1> 	test	byte [i.flgs+1], 10h
  2044                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2045                              <1> 			  	     ; is this a large or small file
  2046 00005171 756A                <1> 	jnz 	short mget_5 ; 4f ; large file
  2047                              <1> 
  2048 00005173 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2049                              <1> 		; bit $!17,r2
  2050 00005176 7525                <1> 	jnz 	short mget_2
  2051                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2052 00005178 80E30E              <1>         and     bl, 0Eh  
  2053                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2054 0000517B 0FB783[DC6C0000]    <1> 	movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2055                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2056                              <1> 	; 24/12/2021
  2057 00005182 09C0                <1> 	or	eax, eax
  2058                              <1> 	;or 	ax, ax
  2059 00005184 7516                <1> 	jnz 	short mget_1 
  2060                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2061                              <1> 		       ; / for file
  2062 00005186 E8A7000000          <1> 	call 	alloc
  2063                              <1> 		; jsr r0,alloc / allocate a new block
  2064                              <1>          ; eAX (r1) = Physical block number
  2065 0000518B 668983[DC6C0000]    <1> 	mov 	[ebx+i.dskp], ax
  2066                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2067 00005192 E841020000          <1> 	call 	setimod	
  2068                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2069 00005197 E8BBFEFFFF          <1> 	call	clear
  2070                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2071                              <1> mget_1: ; 2:
  2072                              <1>         ; eAX (r1) = Physical block number
  2073 0000519C C3                  <1> 	retn 
  2074                              <1> 		; rts r0
  2075                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2076 0000519D E890000000          <1> 	call 	alloc
  2077                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2078                              <1> 	                     ; / block number in r1
  2079                              <1>         ; eAX (r1) = Physical block number
  2080 000051A2 E83E0C0000          <1> 	call 	wslot
  2081                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2082                              <1> 			     ; / first data word in buffer
  2083                              <1>         ; eAX (r1) = Physical block number
  2084 000051A7 B908000000          <1> 	mov 	ecx, 8  ; R3, transfer old physical block pointers
  2085                              <1> 		   ; into new indirect block area for the new
  2086                              <1> 		   ; large file		
  2087 000051AC 89DF                <1> 	mov 	edi, ebx ; r5
  2088 000051AE BE[DC6C0000]        <1> 	mov 	esi, i.dskp 
  2089                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2090                              <1> 			   ; / block pointers
  2091                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2092                              <1> 			  ; / large file
  2093                              <1> 	;xor 	ax, ax ; mov ax, 0
  2094                              <1> 	; 24/12/2021
  2095 000051B3 31C0                <1> 	xor	eax, eax
  2096                              <1> mget_3: ;1:
  2097 000051B5 66A5                <1> 	movsw
  2098                              <1> 		; mov (r2),(r5)+
  2099 000051B7 668946FE            <1> 	mov 	[esi-2], ax
  2100                              <1> 		; clr (r2)+
  2101 000051BB E2F8                <1> 	loop	mget_3 ; 1b
  2102                              <1> 		; dec r3
  2103                              <1> 		; bgt 1b
  2104                              <1> 
  2105 000051BD B1F8                <1> 	mov 	cl, 256-8
  2106                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2107                              <1> mget_4:	; 1
  2108 000051BF F366AB              <1> 	rep 	stosw
  2109                              <1> 		; clr (r5)+
  2110                              <1> 		; dec r3
  2111                              <1> 		; bgt 1b
  2112                              <1> 	; 24/03/2013
  2113                              <1>         ; AX (r1) = Physical block number
  2114 000051C2 E83A0C0000          <1> 	call	dskwr
  2115                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2116                              <1>         ; eAX (r1) = Physical block number
  2117 000051C7 66A3[DC6C0000]      <1> 	mov 	[i.dskp], ax
  2118                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2119 000051CD 66810D[D66C0000]00- <1> 	or 	word [i.flgs], 4096 ; 1000h
  2119 000051D5 10                  <1>
  2120                              <1> 		; bis $10000,i.flgs / set large file bit 
  2121                              <1> 				  ; / in i.flgs word of i-node
  2122 000051D6 E8FD010000          <1> 	call	setimod
  2123                              <1> 		; jsr r0,setimod / set i-node modified flag
  2124 000051DB EB83                <1>         jmp     mget_0 
  2125                              <1> 		; br mget
  2126                              <1> 
  2127                              <1> mget_5:  ; 4 ; large file
  2128                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2129                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2130                              <1> 			    ; / in indirect block
  2131                              <1> 		; mov r2,-(sp) / save on stack (*)
  2132                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2133                              <1>        		          ; / indirect block
  2134                              <1> 		; bic $!16,r2
  2135 000051DD 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2136 000051E0 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2137                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2138                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2139                              <1> 	; There is always 1 indirect block for this file system
  2140 000051E1 0FB705[DC6C0000]    <1> 	movzx 	eax, word [i.dskp] ; i.dskp[0]
  2141                              <1> 		; mov i.dskp(r2),r1
  2142 000051E8 6609C0              <1> 	or 	ax, ax ; R1
  2143 000051EB 7515                <1> 	jnz 	short mget_6 ; 2f
  2144                              <1> 		; bne 2f / if no indirect block exists
  2145 000051ED E840000000          <1> 	call 	alloc
  2146                              <1> 		; jsr r0,alloc / allocate a new block
  2147 000051F2 66A3[DC6C0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2148                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2149 000051F8 E8DB010000          <1> 	call 	setimod
  2150                              <1> 		; jsr r0,setimod / set i-node modified byte
  2151                              <1> 	; eAX = new block number
  2152 000051FD E855FEFFFF          <1> 	call 	clear
  2153                              <1> 		; jsr r0,clear / clear new block
  2154                              <1> mget_6: ;2
  2155                              <1> 	; 05/03/2013
  2156                              <1> 	; eAX = r1, physical block number (of indirect block)
  2157 00005202 E87E0B0000          <1> 	call 	dskrd ; read indirect block
  2158                              <1> 		; jsr r0,dskrd / read in indirect block
  2159 00005207 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2160                              <1> 		; mov (sp)+,r2 / get offset
  2161                              <1> 	; eAX = r1, physical block number (of indirect block)
  2162 00005208 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2163                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2164                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2165 00005209 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2166                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2167                              <1> 	                  ; / points to location of inter
  2168 0000520B 0FB703              <1> 	movzx 	eax, word [ebx] ; put physical block no of block
  2169                              <1> 			      ; in file sought in R1 (AX)
  2170                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2171                              <1> 	               	    ; / sought in r1
  2172 0000520E 6609C0              <1> 	or 	ax, ax
  2173 00005211 751D                <1>         jnz 	short mget_7 ; 2f
  2174                              <1> 		; bne 2f / if no block exists 
  2175 00005213 E81A000000          <1> 	call 	alloc
  2176                              <1> 		; jsr r0,alloc / allocate a new block
  2177 00005218 668903              <1> 	mov 	[ebx], ax ; R1
  2178                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2179                              <1> 	                    ; / indirect block
  2180 0000521B 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2181                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2182 0000521C 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2183 0000521D 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2184 0000521E 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2185                              <1> 		; mov (r2),-(sp) / save block number of new block
  2186                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2187 00005220 E8C00B0000          <1> 	call 	wslot
  2188                              <1> 		; jsr r0,wslot
  2189                              <1>         ; eAX (r1) = physical block number
  2190                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2191 00005225 E8D70B0000          <1> 	call 	dskwr
  2192                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2193                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2194                              <1> 			     ; / back out on disk
  2195 0000522A 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2196                              <1> 		; mov (sp),r1 / restore block number of new block	
  2197                              <1> 	; eAX (r1) = physical block number of new block
  2198 0000522B E827FEFFFF          <1> 	call 	clear
  2199                              <1> 		; jsr r0,clear / clear new block	
  2200                              <1> mget_7: ; 2
  2201 00005230 5A                  <1> 	pop 	edx ; **
  2202                              <1> 		; tst (sp)+ / bump stack pointer
  2203                              <1> 	; eAX (r1) = Block number of new block
  2204 00005231 C3                  <1> 	retn
  2205                              <1> 		; rts r0
  2206                              <1> 
  2207                              <1> alloc:
  2208                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2209                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2210                              <1> 	;
  2211                              <1> 	; get a free block and 
  2212                              <1> 	; set the corresponding bit in the free storage map
  2213                              <1> 	; 
  2214                              <1> 	; INPUTS ->
  2215                              <1> 	;    cdev (current device)
  2216                              <1> 	;    r2 
  2217                              <1> 	;    r3
  2218                              <1> 	; OUTPUTS ->
  2219                              <1> 	;    r1 (physical block number of block assigned)
  2220                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2221                              <1> 	;
  2222                              <1> 	; ((AX = R1)) output
  2223                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2224                              <1>         ;    ((Modified registers: DX, CX))  
  2225                              <1> 
  2226                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2227                              <1> 		;mov r3,-(sp)
  2228                              <1> 	;push 	ecx
  2229 00005232 53                  <1> 	push 	ebx ; R2
  2230                              <1> 	;push 	edx ; R3
  2231 00005233 BB[C87C0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2232                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2233 00005238 803D[EE6F0000]00    <1> 	cmp 	byte [cdev], 0
  2234                              <1> 		; tst cdev
  2235 0000523F 7605                <1> 	jna	short alloc_1
  2236                              <1> 		; beq 1f / drum is device
  2237 00005241 BB[D07E0000]        <1> 	mov	ebx, mount
  2238                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2239                              <1> 			      ; / free storage map
  2240                              <1> alloc_1: ; 1
  2241 00005246 668B0B              <1>         mov	cx, [ebx]
  2242                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2243                              <1> 			     ; / storage map
  2244 00005249 66C1E103            <1> 	shl	cx, 3
  2245                              <1> 		; asl r1 / multiply r1 by eight gives 
  2246                              <1> 		; number of blocks in device
  2247                              <1> 		; asl r1
  2248                              <1> 		; asl r1
  2249                              <1> 	;; push cx ;; 01/08/2013
  2250                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2251 0000524D 31C0                <1> 	xor 	eax, eax ; 0
  2252                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2253                              <1> alloc_2: ; 1
  2254 0000524F 43                  <1> 	inc 	ebx ; 18/8/2012
  2255 00005250 43                  <1> 	inc 	ebx ; 
  2256 00005251 668B13              <1> 	mov 	dx, [ebx]
  2257                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2258 00005254 6609D2              <1> 	or 	dx, dx
  2259 00005257 750E                <1> 	jnz 	short alloc_3 ; 1f
  2260                              <1> 		; bne 1f / branch if any free blocks in this word	
  2261 00005259 6683C010            <1> 	add 	ax, 16
  2262                              <1> 		; add $16.,r1
  2263 0000525D 6639C8              <1> 	cmp 	ax, cx    
  2264                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2265 00005260 72ED                <1> 	jb 	short alloc_2
  2266                              <1> 		; blo 1b
  2267                              <1> 	; 14/11/2015
  2268                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2269                              <1> 	;	because of a (DMA or another) r/w error, 
  2270                              <1> 	;	we will be here, at 'jmp panic' code address,
  2271                              <1> 	;	even if the (disk) file system space is not full !!!
  2272                              <1> 	;	(cx = 0)	
  2273                              <1> 	;
  2274 00005262 E9B6E2FFFF          <1> 	jmp     panic 
  2275                              <1> 		; jmp panic / found no free storage
  2276                              <1> alloc_3: ; 1
  2277 00005267 66D1EA              <1> 	shr	dx, 1
  2278                              <1> 		; asr r3 / find a free block
  2279 0000526A 7204                <1> 	jc	short alloc_4 ; 1f
  2280                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2281                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2282 0000526C 6640                <1> 	inc	ax
  2283                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2284 0000526E EBF7                <1> 	jmp 	short alloc_3
  2285                              <1> 		; br 1b
  2286                              <1> alloc_4: ; 1:
  2287                              <1> 	;; pop cx ;; 01/08/2013
  2288                              <1> 		; tst (sp)+ / bump sp
  2289                              <1> 	; 02/04/2013 
  2290 00005270 E829000000          <1> 	call	free3
  2291                              <1> 		; jsr r0,3f / have found a free block
  2292                              <1> 	; 21/8/2012
  2293 00005275 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2294 00005278 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2295                              <1> 		; bic r3,(r2) / set bit for this block 
  2296                              <1> 		            ; / i.e. assign block
  2297                              <1> 		; br 2f
  2298 0000527B EB09                <1> 	jmp 	short alloc_5
  2299                              <1> 
  2300                              <1> free:
  2301                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2302                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2303                              <1> 	;
  2304                              <1> 	; calculates byte address and bit position for given block number
  2305                              <1> 	; then sets the corresponding bit in the free storage map
  2306                              <1> 	; 
  2307                              <1> 	; INPUTS ->
  2308                              <1> 	;    r1 - block number for a block structured device
  2309                              <1> 	;    cdev - current device 
  2310                              <1> 	; OUTPUTS ->
  2311                              <1> 	;    free storage map is updated
  2312                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2313                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2314                              <1> 	;
  2315                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2316                              <1>         ;  ((Modified registers: DX, CX))  
  2317                              <1> 
  2318                              <1> 		;mov r2,-(sp) / save r2, r3
  2319                              <1> 		;mov r3,-(sp)
  2320                              <1> 	;push 	ecx
  2321 0000527D 53                  <1> 	push 	ebx ; R2
  2322                              <1> 	;push 	edx ; R3 
  2323                              <1> 
  2324 0000527E E81B000000          <1>         call    free3
  2325                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2326                              <1> 				 ; / in free storage map for block
  2327 00005283 660913              <1> 	or 	[ebx], dx  
  2328                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2329                              <1> 			    ;  / indicates free block	
  2330                              <1> 	; 0 -> allocated, 1 -> free
  2331                              <1> 
  2332                              <1> alloc_5:
  2333                              <1> 	; 07/04/2013
  2334                              <1> free_1: ; 2:
  2335                              <1> 	; pop 	edx
  2336                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2337 00005286 5B                  <1> 	pop	ebx
  2338                              <1> 		; mov (sp)+,r2
  2339                              <1> 	; pop	ecx
  2340 00005287 803D[EE6F0000]00    <1> 	cmp 	byte [cdev], 0
  2341                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2342                              <1> 			 ; / cdev = 1, mountable device
  2343 0000528E 7707                <1> 	ja	short alloc_6 ; 1f
  2344                              <1> 		; bne 1f
  2345                              <1> 	;mov	byte [smod], 1
  2346 00005290 FE05[FD6F0000]      <1> 	inc 	byte [smod]
  2347                              <1> 		; incb smod / set super block modified for drum
  2348                              <1> 	; eAX (r1) = block number
  2349 00005296 C3                  <1> 	retn
  2350                              <1> 		; rts r0
  2351                              <1> free_2:
  2352                              <1> alloc_6: ; 1:
  2353                              <1> 	;mov 	byte [mmod], 1
  2354 00005297 FE05[FE6F0000]      <1> 	inc 	byte [mmod]
  2355                              <1> 		; incb	mmod 
  2356                              <1> 		  ; / set super block modified for mountable device
  2357                              <1> 	; eAX (r1) = block number
  2358 0000529D C3                  <1> 	retn	
  2359                              <1> 		; rts r0
  2360                              <1> free3:
  2361                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2362                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2363                              <1> 	;
  2364                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2365                              <1> 	; 
  2366                              <1> alloc_free_3: ; 3
  2367 0000529E 66BA0100            <1> 	mov 	dx, 1
  2368 000052A2 88C1                <1> 	mov 	cl, al
  2369                              <1> 		; mov r1,r2 / block number, k, = 1		
  2370 000052A4 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2371                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2372 000052A7 7403                <1> 	jz 	short free4
  2373                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2374                              <1> 			       ; / (k) mod 8
  2375 000052A9 66D3E2              <1> 	shl 	dx, cl
  2376                              <1> free4:
  2377 000052AC 0FB7D8              <1> 	movzx 	ebx, ax
  2378                              <1> 		; mov r1,r2 / divide block number by 16
  2379 000052AF 66C1EB04            <1> 	shr 	bx, 4
  2380                              <1> 		; asr r2
  2381                              <1> 		; asr r2
  2382                              <1> 		; asr r2
  2383                              <1> 		; asr r2
  2384                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2385                              <1> 		       ; / bit for block is in lower half of word
  2386                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2387                              <1> 		        ; / storage map
  2388                              <1> alloc_free_4: ; 1
  2389 000052B3 66D1E3              <1> 	shl 	bx, 1
  2390                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2391 000052B6 81C3[CA7C0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2392                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2393                              <1> 	    		        ; / with block bit in it 	
  2394 000052BC 803D[EE6F0000]00    <1> 	cmp	byte [cdev], 0
  2395                              <1> 		; tst cdev
  2396 000052C3 7606                <1> 	jna	short alloc_free_5
  2397                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2398 000052C5 81C308020000        <1> 	add	ebx, mount - systm
  2399                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2400                              <1> 				    ; / mountable device with bit of block to be
  2401                              <1> 				    ; / freed
  2402                              <1> alloc_free_5: ; 1 
  2403 000052CB C3                  <1> 	retn
  2404                              <1> 		; rts r0 / return to 'free'
  2405                              <1> 	      ; 2
  2406                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2407                              <1> 	
  2408                              <1> iget:
  2409                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2410                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2411                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2412                              <1> 	;
  2413                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2414                              <1> 	;
  2415                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2416                              <1> 	; 
  2417                              <1> 	; INPUTS ->
  2418                              <1> 	;    ii - current i-number, rootdir
  2419                              <1> 	;    cdev - new i-node device
  2420                              <1> 	;    idev - current i-node device
  2421                              <1> 	;    imod - current i-node modified flag
  2422                              <1> 	;    mnti - cross device file i-number
  2423                              <1> 	;    r1 - i-numbe rof new i-node
  2424                              <1> 	;    mntd - mountable device number		
  2425                              <1> 	; 	 
  2426                              <1> 	; OUTPUTS ->
  2427                              <1> 	;    cdev, idev, imod, ii, r1
  2428                              <1> 	;
  2429                              <1> 	; ((AX = R1)) input/output
  2430                              <1> 	;
  2431                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2432                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2433                              <1> 
  2434 000052CC 8A15[EE6F0000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2435 000052D2 8A35[EC6F0000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2436                              <1> 	;
  2437 000052D8 663B05[EA6F0000]    <1> 	cmp 	ax, [ii]
  2438                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2439 000052DF 7504                <1> 	jne 	short iget_1
  2440                              <1> 		; bne 1f
  2441 000052E1 38F2                <1> 	cmp	dl, dh
  2442                              <1> 		; cmp idev,cdev
  2443                              <1> 			  ; / is device number of i-node = current device
  2444 000052E3 7472                <1>         je      short iget_5
  2445                              <1> 		; beq 2f
  2446                              <1> iget_1: ; 1:
  2447 000052E5 30DB                <1> 	xor	bl, bl
  2448 000052E7 381D[FC6F0000]      <1> 	cmp	[imod], bl ; 0	
  2449                              <1> 		; tstb imod / has i-node of current file
  2450                              <1> 			  ; / been modified i.e., imod set
  2451 000052ED 7629                <1> 	jna	short iget_2
  2452                              <1> 		; beq 1f
  2453 000052EF 881D[FC6F0000]      <1> 	mov	[imod], bl ; 0
  2454                              <1> 		;  clrb	imod / if it has, 
  2455                              <1> 			   ; / we must write the new i-node out on disk
  2456                              <1> 	; 24/12/2021
  2457 000052F5 50                  <1> 	push	eax ; *
  2458                              <1> 	;push	ax
  2459                              <1> 		; mov r1,-(sp)
  2460                              <1> 	;mov	dl, [cdev]
  2461 000052F6 52                  <1> 	push	edx ; **
  2462                              <1> 	;push	dx
  2463                              <1> 		; mov cdev,-(sp)
  2464 000052F7 66A1[EA6F0000]      <1> 	mov	ax, [ii]
  2465                              <1> 		; mov ii,r1
  2466                              <1> 	;mov	dh, [idev]
  2467 000052FD 8835[EE6F0000]      <1> 	mov	[cdev], dh
  2468                              <1> 		; mov idev,cdev
  2469 00005303 FEC3                <1> 	inc	bl ; 1
  2470                              <1> 	; 31/07/2013
  2471 00005305 881D[8C700000]      <1> 	mov     [rw], bl ; 1 == write 
  2472                              <1> 	;;28/07/2013 rw -> u.rw
  2473                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2474 0000530B E848000000          <1> 	call	icalc
  2475                              <1> 		; jsr r0,icalc; 1
  2476                              <1> 	;pop	dx
  2477                              <1> 	; 24/12/2021
  2478 00005310 5A                  <1> 	pop	edx ; **
  2479 00005311 8815[EE6F0000]      <1> 	mov	[cdev], dl
  2480                              <1> 		; mov (sp)+,cdev
  2481                              <1> 	; 24/12/2021
  2482 00005317 58                  <1> 	pop	eax ; *
  2483                              <1> 	;pop	ax
  2484                              <1> 		; mov (sp)+,r1
  2485                              <1> iget_2: ; 1:
  2486 00005318 6621C0              <1> 	and	ax, ax
  2487                              <1> 		; tst r1 / is new i-number non zero
  2488 0000531B 7434                <1> 	jz	short iget_4 ; 2f
  2489                              <1> 		; beq 2f / branch if r1=0
  2490                              <1> 
  2491                              <1> 	; mov 	dl, [cdev]
  2492 0000531D 08D2                <1> 	or	dl, dl
  2493                              <1> 		; tst cdev / is the current device number non zero
  2494                              <1> 			 ; / (i.e., device =/ drum)
  2495 0000531F 7517                <1> 	jnz	short iget_3 ;  1f
  2496                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2497 00005321 663B05[F46F0000]    <1> 	cmp	ax, [mnti]			
  2498                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2499                              <1> 			    ; / file (root directory of mounted device)
  2500 00005328 750E                <1> 	jne	short iget_3 ; 1f
  2501                              <1> 		; bne 1f
  2502                              <1>         ;mov    bl, [mntd]
  2503 0000532A FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2504 0000532C 8815[EE6F0000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2505                              <1> 		; mov mntd,cdev / make mounted device the current device
  2506 00005332 66A1[F86F0000]      <1> 	mov	ax, [rootdir]
  2507                              <1> 		; mov rootdir,r1
  2508                              <1> iget_3: ; 1:
  2509 00005338 66A3[EA6F0000]      <1> 	mov	[ii], ax
  2510                              <1> 		; mov r1,ii
  2511 0000533E 8815[EC6F0000]      <1> 	mov	[idev], dl ; cdev
  2512                              <1> 		; mov cdev,idev
  2513 00005344 30DB                <1> 	xor	bl, bl
  2514                              <1>         ; 31/07/2013
  2515 00005346 881D[8C700000]      <1> 	mov     [rw], bl ; 0 == read 
  2516                              <1> 	;;28/07/2013 rw -> u.rw       
  2517                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2518 0000534C E807000000          <1> 	call	icalc
  2519                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2520                              <1> iget_4: ; 2:
  2521 00005351 66A1[EA6F0000]      <1> 	mov	ax, [ii]
  2522                              <1> 		; mov ii,r1
  2523                              <1> iget_5:
  2524 00005357 C3                  <1> 	retn
  2525                              <1> 		; rts r0
  2526                              <1> 
  2527                              <1> icalc:
  2528                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2529                              <1> 	; 02/07/2015
  2530                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2531                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2532                              <1> 	;
  2533                              <1> 	; calculate physical block number from i-number then
  2534                              <1> 	; read or write that block
  2535                              <1> 	;
  2536                              <1> 	; 'icalc' is called from 'iget'
  2537                              <1> 	;
  2538                              <1> 	; for original unix v1:
  2539                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2540                              <1>        	; / (i+31.) mod 16. bytes from its start
  2541                              <1> 	;
  2542                              <1> 	; for retro unix 8086 v1:
  2543                              <1> 	;  i-node is located in block (i+47)/16 and
  2544                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2545                              <1> 	;
  2546                              <1> 	; INPUTS ->
  2547                              <1> 	;    r1 - i-number of i-node
  2548                              <1> 	; 	 
  2549                              <1> 	; OUTPUTS ->
  2550                              <1> 	;    inode r/w
  2551                              <1> 	;
  2552                              <1> 	; ((AX = R1)) input
  2553                              <1> 	;
  2554                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2555                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2556                              <1> 	;
  2557 00005358 0FB7D0              <1> 	movzx	edx, ax	
  2558 0000535B 6683C22F            <1> 	add	dx, 47
  2559 0000535F 89D0                <1> 	mov	eax, edx
  2560                              <1> 	;add	ax, 47	; add 47 to inode number
  2561                              <1> 		; add $31.,r1 / add 31. to i-number
  2562 00005361 50                  <1> 	push	eax
  2563                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2564 00005362 66C1E804            <1> 	shr 	ax, 4
  2565                              <1> 		; asr r1 / divide by 16.
  2566                              <1> 		; asr r1
  2567                              <1> 		; asr r1
  2568                              <1> 		; asr r1 / r1 contains block number of block
  2569                              <1> 		       ; / in which i-node exists
  2570 00005366 E81A0A0000          <1> 	call	dskrd
  2571                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2572                              <1> 	; 31/07/2013
  2573 0000536B 803D[8C700000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2574                              <1> 	;; 28/07/2013 rw -> u.rw
  2575                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2576                              <1> 		; tst (r0)
  2577 00005372 7605                <1> 	jna	short icalc_1
  2578                              <1> 		; beq 1f / branch to wslot when argument
  2579                              <1> 		       ; / in icalc call = 1
  2580                              <1> 	; eAX = r1  = block number
  2581 00005374 E86C0A0000          <1> 	call	wslot
  2582                              <1> 		; jsr r0,wslot / set up data buffer for write
  2583                              <1> 			     ; / (will be same buffer as dskrd got)
  2584                              <1> 	; eBX = r5 points to first word in data area for this block
  2585                              <1> icalc_1: ; 1:
  2586 00005379 5A                  <1> 	pop	edx 
  2587 0000537A 83E20F              <1> 	and 	edx, 0Fh ; (i+47) mod 16
  2588                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2589                              <1> 			      ; / gives (i+31.) mod 16
  2590 0000537D C1E205              <1> 	shl 	edx, 5
  2591                              <1> 	; eDX = 32 * ((i+47) mod 16)
  2592 00005380 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2593 00005382 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2594                              <1>           	; eSI (r5) points to first word in i-node i.	
  2595                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2596                              <1> 			     ; / 32.*(i+31.)mod16
  2597                              <1> 		; mov $5,lsh / for i-node i.
  2598                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2599 00005384 BF[D66C0000]        <1> 	mov	edi, inode
  2600                              <1> 		; mov $inode,r1 / inode is address of first word 
  2601                              <1> 			      ; / of current i-node
  2602 00005389 B908000000          <1> 	mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2603                              <1> 		; mov $16.,r3
  2604                              <1>        ; 31/07/2013
  2605 0000538E 382D[8C700000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2606                              <1>        ;;28/07/2013 rw -> u.rw                 
  2607                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2608                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2609 00005394 7609                <1> 	jna	short icalc_3
  2610                              <1> 		; beq 2f / r0 now contains proper return address 
  2611                              <1> 		       ; / for rts r0
  2612                              <1> icalc_2: ; 1:
  2613 00005396 87F7                <1> 	xchg 	esi, edi
  2614                              <1> 	; overwrite old i-node (in buffer to be written)
  2615 00005398 F3A5                <1> 	rep 	movsd
  2616                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2617                              <1> 		; dec r3
  2618                              <1> 		; bgt 1b
  2619                              <1> 	;call	dskwr
  2620                              <1> 		; jsr r0,dskwr / write inode out on device
  2621                              <1> 	;retn
  2622                              <1> 		; rts r0
  2623                              <1> 	; 24/12/2021
  2624 0000539A E9620A0000          <1> 	jmp	dskwr
  2625                              <1> 
  2626                              <1> icalc_3: ; 2:
  2627                              <1> 	; copy new i-node into inode area of (core) memory
  2628 0000539F F3A5                <1> 	rep 	movsd
  2629                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2630                              <1> 		                ; / "inode" area of core
  2631                              <1> 		; dec r3
  2632                              <1> 		; bgt 2b
  2633 000053A1 C3                  <1> 	retn
  2634                              <1> 		; rts r0
  2635                              <1> 
  2636                              <1> access:
  2637                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2638                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2639                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2640                              <1> 	;
  2641                              <1> 	; check whether user is owner of file or user has read or write
  2642                              <1> 	; permission (based on i.flgs).
  2643                              <1> 	;
  2644                              <1> 	; INPUTS ->
  2645                              <1> 	;    r1 - i-number of file
  2646                              <1> 	;    u.uid
  2647                              <1> 	; arg0 -> (owner flag mask)	 		
  2648                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2649                              <1> 	; OUTPUTS ->
  2650                              <1> 	;    inode (or jump to error)
  2651                              <1> 	;
  2652                              <1> 	; ((AX = R1)) input/output
  2653                              <1> 	;
  2654                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2655                              <1> 	
  2656                              <1> 	;push	dx  ; save flags (DL)
  2657                              <1> 	; 24/12/2021
  2658 000053A2 52                  <1> 	push	edx ; save flags (DL)
  2659 000053A3 E824FFFFFF          <1> 	call	iget
  2660                              <1> 		; jsr r0,iget / read in i-node for current directory
  2661                              <1> 			    ; / (i-number passed in r1)
  2662 000053A8 8A0D[D66C0000]      <1> 	mov	cl, [i.flgs]
  2663                              <1> 		; mov i.flgs,r2
  2664                              <1> 	; 24/12/2021
  2665 000053AE 5A                  <1> 	pop	edx ; restore flags (DL)
  2666                              <1> 	;pop	dx  ; restore flags (DL)
  2667 000053AF 8A35[54700000]      <1> 	mov	dh, [u.uid]
  2668 000053B5 3A35[D96C0000]      <1> 	cmp	dh, [i.uid]
  2669                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2670 000053BB 7503                <1> 	jne	short access_1
  2671                              <1> 		; bne 1f / no, then branch
  2672 000053BD C0E902              <1> 	shr	cl, 2
  2673                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2674                              <1> 		        ; / read/write bits
  2675                              <1> 		; asrb r2
  2676                              <1> access_1: ; 1:
  2677 000053C0 20D1                <1> 	and	cl, dl
  2678                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2679                              <1> 			     ; / in access call
  2680 000053C2 7513                <1> 	jnz	short access_2
  2681                              <1> 		; bne 1f
  2682 000053C4 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2683                              <1> 		; tstb u.uid
  2684 000053C6 740F                <1> 	jz	short access_2 ; yes, super user
  2685                              <1> 	;jnz	error
  2686                              <1> 		; beq 1f
  2687                              <1> 		; jmp error
  2688 000053C8 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2688 000053D0 0000                <1>
  2689                              <1> 			; 'permission denied !' error
  2690 000053D2 E9AEE8FFFF          <1> 	jmp	error
  2691                              <1> 
  2692                              <1> access_2: ; 1:
  2693                              <1> 	; DL = flags
  2694 000053D7 C3                  <1> 	retn
  2695                              <1> 		; rts r0
  2696                              <1> 
  2697                              <1> setimod:
  2698                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2699                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2700                              <1> 	;
  2701                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2702                              <1> 	; the inode has been modified. Also puts the time of modification
  2703                              <1> 	; into the inode.
  2704                              <1> 	;
  2705                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2706                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2707                              <1> 	;
  2708                              <1> 	
  2709                              <1> 	;push 	edx
  2710 000053D8 50                  <1> 	push	eax
  2711                              <1> 
  2712 000053D9 C605[FC6F0000]01    <1> 	mov 	byte [imod], 1
  2713                              <1> 		; movb $1,imod / set current i-node modified bytes
  2714                              <1> 	; Erdogan Tan 14-7-2012
  2715 000053E0 E8DAE3FFFF          <1> 	call 	epoch
  2716                              <1> 		 ; mov s.time,i.mtim 
  2717                              <1> 			    ; / put present time into file modified time
  2718                              <1> 		 ; mov s.time+2,i.mtim+2
  2719                              <1> 
  2720 000053E5 A3[F06C0000]        <1> 	mov 	[i.mtim], eax
  2721                              <1> 	
  2722                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2723                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2724 000053EA 833D[EC6C0000]00    <1> 	cmp	dword [i.ctim], 0
  2725 000053F1 7505                <1> 	jnz	short setimod_ok
  2726                              <1> 
  2727 000053F3 A3[EC6C0000]        <1> 	mov 	[i.ctim], eax
  2728                              <1> 
  2729                              <1> setimod_ok: ; 31/07/2013
  2730 000053F8 58                  <1> 	pop	eax
  2731                              <1> 	;pop	edx
  2732                              <1> 	
  2733 000053F9 C3                  <1> 	retn
  2734                              <1> 		; rts r0
  2735                              <1> 
  2736                              <1> itrunc:
  2737                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2738                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2739                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2740                              <1> 	;
  2741                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2742                              <1> 	;  to zero length.
  2743                              <1> 	;
  2744                              <1> 	; INPUTS ->
  2745                              <1> 	;    r1 - i-number of i-node
  2746                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2747                              <1> 	;    i.flgs - large file flag		
  2748                              <1> 	;    i.size - size of file	
  2749                              <1> 	; 	 
  2750                              <1> 	; OUTPUTS ->
  2751                              <1> 	;    i.flgs - large file flag is cleared
  2752                              <1> 	;    i.size - set to 0	
  2753                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2754                              <1> 	;    setimod - set to indicate i-node has been modified
  2755                              <1> 	;    r1 - i-number of i-node  					
  2756                              <1> 	;
  2757                              <1> 	; ((AX = R1)) input/output
  2758                              <1> 	;
  2759                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2760                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2761                              <1> 
  2762 000053FA E8CDFEFFFF          <1> 	call	iget
  2763                              <1> 		; jsr r0,iget
  2764 000053FF BE[DC6C0000]        <1> 	mov	esi, i.dskp
  2765                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2766 00005404 31C0                <1> 	xor	eax, eax
  2767                              <1> itrunc_1: ; 1:
  2768 00005406 66AD                <1> 	lodsw
  2769                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2770 00005408 6609C0              <1> 	or 	ax, ax
  2771 0000540B 7439                <1> 	jz	short itrunc_5
  2772                              <1> 		; beq 5f
  2773 0000540D 56                  <1> 	push	esi
  2774                              <1> 		; mov r2,-(sp)
  2775 0000540E 66F705[D66C0000]00- <1> 	test    word [i.flgs], 1000h    
  2775 00005416 10                  <1>
  2776                              <1> 		; bit $10000,i.flgs / test large file bit?
  2777 00005417 7427                <1> 	jz	short itrunc_4
  2778                              <1> 		; beq 4f / if clear, branch
  2779 00005419 50                  <1> 	push	eax
  2780                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2781 0000541A E866090000          <1> 	call	dskrd
  2782                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2783                              <1> 			     ; / pointed to by r5
  2784                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2785 0000541F B900010000          <1> 	mov	ecx, 256
  2786                              <1> 		; mov $256.,r3 / move word count into r3
  2787 00005424 89DE                <1> 	mov	esi, ebx
  2788                              <1> itrunc_2: ; 2:
  2789 00005426 66AD                <1> 	lodsw
  2790                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2791                              <1> 			     ; / physical block number
  2792 00005428 6621C0              <1> 	and	ax, ax
  2793 0000542B 7407                <1> 	jz	short itrunc_3
  2794                              <1> 		; beq 3f / branch if zero
  2795                              <1> 	; 24/12/2021
  2796 0000542D 51                  <1> 	push	ecx
  2797                              <1> 	;push	cx
  2798                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2799                              <1> 	;push	esi
  2800                              <1> 		; mov r5,-(sp)
  2801 0000542E E84AFEFFFF          <1> 	call	free
  2802                              <1> 		; jsr r0,free / free block in free storage map
  2803                              <1> 	;pop	esi
  2804                              <1> 		; mov(sp)+,r5
  2805                              <1> 	;pop	cx
  2806 00005433 59                  <1> 	pop	ecx
  2807                              <1> 		; mov (sp)+,r3
  2808                              <1> itrunc_3: ; 3:
  2809 00005434 E2F0                <1> 	loop	itrunc_2
  2810                              <1> 		; dec r3 / decrement word count
  2811                              <1> 		; bgt 2b / branch if positive
  2812 00005436 58                  <1> 	pop	eax
  2813                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2814                              <1> 			     ; / indirect block
  2815                              <1> 	; 01/08/2013
  2816 00005437 668125[D66C0000]FF- <1>         and     word [i.flgs], 0EFFFh ; 1110111111111111b
  2816 0000543F EF                  <1>
  2817                              <1> itrunc_4: ; 4:
  2818 00005440 E838FEFFFF          <1> 	call	free
  2819                              <1> 		; jsr r0,free / free indirect block
  2820 00005445 5E                  <1> 	pop	esi
  2821                              <1> 		; mov (sp)+,r2
  2822                              <1> itrunc_5: ; 5:
  2823 00005446 81FE[EC6C0000]      <1> 	cmp	esi, i.dskp+16
  2824                              <1> 		; cmp r2,$i.dskp+16.
  2825 0000544C 72B8                <1> 	jb	short itrunc_1	
  2826                              <1> 		; bne 1b / branch until all i.dskp entries check
  2827                              <1> 	; 01/08/2013
  2828                              <1> 	;and     word [i.flgs], 0EFFFh ; 1110111111111111b
  2829                              <1> 		; bic $10000,i.flgs / clear large file bit
  2830 0000544E BF[DC6C0000]        <1> 	mov	edi, i.dskp
  2831 00005453 66B90800            <1> 	mov	cx, 8
  2832 00005457 6631C0              <1> 	xor 	ax, ax
  2833 0000545A 66A3[DA6C0000]      <1> 	mov	[i.size], ax ; 0
  2834                              <1> 		; clr i.size / zero file size
  2835 00005460 F366AB              <1> 	rep	stosw
  2836                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2837                              <1> 			   ; / zero block pointers
  2838 00005463 E870FFFFFF          <1> 	call	setimod
  2839                              <1> 		; jsr r0,setimod / set i-node modified flag
  2840 00005468 66A1[EA6F0000]      <1> 	mov	ax, [ii]
  2841                              <1> 		; mov ii,r1
  2842 0000546E C3                  <1> 	retn
  2843                              <1> 		; rts r0
  2844                              <1> 
  2845                              <1> imap:
  2846                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2847                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  2848                              <1> 	;
  2849                              <1> 	; 'imap' finds the byte in core (superblock) containing
  2850                              <1> 	; allocation bit for an i-node whose number in r1.
  2851                              <1> 	;
  2852                              <1> 	; INPUTS ->
  2853                              <1> 	;    r1 - contains an i-number
  2854                              <1> 	;    fsp - start of table containing open files
  2855                              <1> 	;
  2856                              <1> 	; OUTPUTS ->
  2857                              <1> 	;    r2 - byte address of byte with the allocation bit
  2858                              <1> 	;    mq - a mask to locate the bit position.	
  2859                              <1> 	;	  (a 1 is in calculated bit posisiton)
  2860                              <1> 	;
  2861                              <1> 	; ((AX = R1)) input/output
  2862                              <1> 	; ((DL/DX = MQ)) output
  2863                              <1> 	; ((BX = R2)) output
  2864                              <1> 	;
  2865                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  2866                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  2867                              <1> 	;
  2868                              <1> 		; / get the byte that has the allocation bit for 
  2869                              <1> 		; / the i-number contained in r1
  2870                              <1> 	;mov	dx, 1
  2871 0000546F B201                <1> 	mov	dl, 1
  2872                              <1> 		; mov $1,mq / put 1 in the mq
  2873 00005471 0FB7D8              <1> 	movzx	ebx, ax
  2874                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  2875                              <1>  		          ; / in the map we must find
  2876 00005474 6683EB29            <1> 	sub	bx, 41
  2877                              <1> 		; sub $41.,r2 / r2 has i-41
  2878 00005478 88D9                <1> 	mov	cl, bl
  2879                              <1> 		; mov r2,r3 / r3 has i-41
  2880 0000547A 80E107              <1> 	and	cl, 7
  2881                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  2882                              <1> 			   ; / the bit position
  2883 0000547D 7402                <1> 	jz	short imap1
  2884                              <1> 	;shl	dx, cl
  2885 0000547F D2E2                <1> 	shl	dl, cl
  2886                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  2887                              <1> imap1:			   ; / to the left to mask the correct bit
  2888 00005481 66C1EB03            <1> 	shr	bx, 3
  2889                              <1> 		; asr r2
  2890                              <1> 		; asr r2
  2891                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  2892                              <1> 		       ; / from the start of the map
  2893                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  2894 00005485 BE[C87C0000]        <1> 	mov	esi, systm
  2895                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  2896                              <1> 				; / the super block for drum
  2897                              <1> 	;cmp	word [cdev], 0
  2898 0000548A 803D[EE6F0000]00    <1> 	cmp	byte [cdev], 0
  2899                              <1> 		; tst cdev / is the device the disk
  2900 00005491 7606                <1> 	jna	short imap2
  2901                              <1> 		; beq 1f / yes
  2902 00005493 81C608020000        <1> 	add	esi, mount - systm
  2903                              <1> 		; add $mount-systm,r2 / for mounted device,
  2904                              <1> 			; / r2 points to 1st word of its super block
  2905                              <1> imap2: ; 1:
  2906 00005499 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  2907                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  2908 0000549C 6683C304            <1> 	add	bx, 4
  2909 000054A0 01F3                <1> 	add	ebx, esi
  2910                              <1>         	; add (sp)+,r2 / ?
  2911                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  2912                              <1> 		      ;; (2 + free map size + 2)
  2913                              <1> 		; add $2,r2 / ?
  2914                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  2915                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  2916 000054A2 C3                  <1> 	retn
  2917                              <1> 		; rts r0
  1998                                  %include 'u6.s'        ; 31/05/2015
  1999                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS6.INC
  2000                              <1> ; Last Modification: 31/12/2021
  2001                              <1> ; ----------------------------------------------------------------------------
  2002                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2003                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2004                              <1> ;
  2005                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2006                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2007                              <1> ; <Bell Laboratories (17/3/1972)>
  2008                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2009                              <1> ;
  2010                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2011                              <1> ;
  2012                              <1> ; ****************************************************************************
  2013                              <1> 
  2014                              <1> readi:
  2015                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2016                              <1> 	; 20/05/2015
  2017                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2018                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2019                              <1> 	;
  2020                              <1> 	; Reads from an inode whose number in R1
  2021                              <1> 	; 
  2022                              <1> 	; INPUTS ->
  2023                              <1> 	;    r1 - inode number
  2024                              <1> 	;    u.count - byte count user desires
  2025                              <1> 	;    u.base - points to user buffer
  2026                              <1> 	;    u.fofp - points to word with current file offset
  2027                              <1> 	; OUTPUTS ->
  2028                              <1> 	;    u.count - cleared
  2029                              <1> 	;    u.nread - accumulates total bytes passed back
  2030                              <1> 	;
  2031                              <1> 	; ((AX = R1)) input/output
  2032                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2033                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2034                              <1> 
  2035 000054A3 31D2                <1> 	xor	edx, edx ; 0
  2036 000054A5 8915[30700000]      <1> 	mov 	[u.nread], edx ; 0
  2037                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2038 000054AB 668915[6D700000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2039 000054B2 3915[2C700000]      <1> 	cmp 	[u.count], edx ; 0
  2040                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2041 000054B8 7701                <1> 	ja 	short readi_1 ; 1f
  2042                              <1> 		 ; bgt 1f / yes, branch
  2043 000054BA C3                  <1> 	retn
  2044                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2045                              <1> readi_1: ; 1:
  2046                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2047 000054BB 6683F828            <1> 	cmp	ax, 40
  2048                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2049                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2050                              <1>         ;ja	dskr 
  2051                              <1> 		 ; ble 1f / yes, branch
  2052                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2053                              <1> 		 ;         / read file with i-node number (r1)
  2054                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2055                              <1> 	; 24/12/2021
  2056 000054BF 7605                <1> 	jna	short readi_3
  2057 000054C1 E9D1000000          <1> 	jmp	dskr
  2058                              <1> readi_3:
  2059                              <1> 	; (20/05/2015)
  2060 000054C6 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2061                              <1> 	; 1:
  2062 000054C7 0FB6D8              <1> 	movzx	ebx, al
  2063 000054CA 66C1E302            <1> 	shl	bx, 2
  2064                              <1> 		 ; asl r1 / multiply inode number by 2
  2065 000054CE 81C3[D2540000]      <1> 	add	ebx, readi_2 - 4
  2066 000054D4 FF23                <1> 	jmp	dword [ebx]	
  2067                              <1> 		 ; jmp *1f-2(r1)
  2068                              <1> readi_2: ; 1:
  2069 000054D6 [22550000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2070                              <1> 		 ;rtty / tty; r1=2
  2071                              <1> 		 ;rppt / ppt; r1=4
  2072 000054DA [73550000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2073                              <1> 		 ;rmem / mem; r1=6
  2074                              <1> 		 ;rrf0 / rf0
  2075                              <1> 		 ;rrk0 / rk0
  2076                              <1> 		 ;rtap / tap0
  2077                              <1> 		 ;rtap / tap1
  2078                              <1> 		 ;rtap / tap2
  2079                              <1> 		 ;rtap / tap3
  2080                              <1> 		 ;rtap / tap4
  2081                              <1> 		 ;rtap / tap5
  2082                              <1> 		 ;rtap / tap6
  2083                              <1> 		 ;rtap / tap7
  2084 000054DE [2B5C0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2085 000054E2 [2B5C0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2086 000054E6 [2B5C0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2087 000054EA [2B5C0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2088 000054EE [2B5C0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2089 000054F2 [2B5C0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2090 000054F6 [88550000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2091 000054FA [6F550000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2092                              <1> 		 ;rcvt / tty0
  2093 000054FE [6F550000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2094                              <1> 		 ;rcvt / tty1
  2095 00005502 [6F550000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2096                              <1> 		 ;rcvt / tty2
  2097 00005506 [6F550000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2098                              <1> 		 ;rcvt / tty3
  2099 0000550A [6F550000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2100                              <1> 		 ;rcvt / tty4
  2101 0000550E [6F550000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2102                              <1> 		 ;rcvt / tty5
  2103 00005512 [6F550000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2104                              <1> 		 ;rcvt / tty6
  2105 00005516 [6F550000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2106                              <1> 		 ;rcvt / tty7
  2107 0000551A [6F550000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2108                              <1> 		 ;rcrd / crd
  2109 0000551E [6F550000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2110                              <1> 
  2111                              <1> rtty: ; / read from console tty
  2112                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2113                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2114                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2115                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2116                              <1> 	;	     must be written immediate on video page (screen)
  2117                              <1> 	;	     when it is required.	
  2118                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2119                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2120                              <1> 	;
  2121                              <1> 	; Console tty buffer is PC keyboard buffer
  2122                              <1> 	; and keyboard-keystroke handling is different than original
  2123                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2124                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2125                              <1> 	;
  2126                              <1> 	; 06/12/2013
  2127 00005522 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2128 00005529 8A83[556D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2129                              <1> rttys:
  2130                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2131                              <1> 	               ; / of the control and status block
  2132                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2133                              <1> 		       ; / tty buffer
  2134                              <1> 	; 28/07/2013
  2135 0000552F A2[5C700000]        <1> 	mov 	[u.ttyn], al
  2136                              <1> 	; 13/01/2014
  2137 00005534 FEC0                <1> 	inc	al
  2138 00005536 A2[38700000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2139                              <1> rtty_nc: ; 01/02/2014
  2140                              <1> 	; 29/09/2013
  2141 0000553B B90A000000          <1> 	mov	ecx, 10
  2142                              <1> rtty_1: 	; 01/02/2014
  2143                              <1> 	;push 	cx ; 29/09/2013
  2144                              <1> 	; 24/12/2021
  2145 00005540 51                  <1> 	push	ecx
  2146                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2147 00005541 B001                <1> 	mov 	al, 1
  2148 00005543 E8260B0000          <1> 	call 	getc
  2149                              <1> 	; 24/12/2021
  2150 00005548 59                  <1> 	pop	ecx
  2151                              <1> 	;pop 	cx ; 29/09/2013	
  2152 00005549 7516                <1> 	jnz	short rtty_2
  2153                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2154                              <1> 	               ; / of chars. Is this number non-zero?
  2155 0000554B E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2156                              <1> 	; 05/10/2013
  2157 0000554D 8A25[5C700000]      <1> 	mov	ah, [u.ttyn]
  2158                              <1> 	; 29/09/2013
  2159 00005553 E888FBFFFF          <1> 	call	sleep
  2160                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2161                              <1>                 ;           / (120 chars.)
  2162                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2163 00005558 EBE1                <1> 	jmp	short rtty_nc ; 01/02/2014
  2164                              <1> 
  2165                              <1> rtty_idle:
  2166                              <1> 	; 29/07/2013
  2167 0000555A E8EEFAFFFF          <1> 	call 	idle
  2168 0000555F EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2169                              <1> 	;1:
  2170                              <1> 		; tst 2(r5) / is the number of characters zero
  2171                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2172                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2173                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2174                              <1> 		          ; / contains the next char.
  2175                              <1> 		; dec 2(r5) / decrement the character count
  2176                              <1> rtty_2:
  2177 00005561 30C0                <1> 	xor 	al, al
  2178 00005563 E8060B0000          <1> 	call 	getc
  2179 00005568 E892000000          <1> 	call	passc
  2180                              <1> 		; jsr r0,passc / move the character to core (user)
  2181                              <1> 	;; 17/10/2015 - 16/07/2015
  2182                              <1> 	; 19/06/2014
  2183                              <1> 	;;jnz	short rtty_nc
  2184 0000556D 58                  <1> 	pop	eax  ; (20/05/2015)
  2185 0000556E C3                  <1> 	retn 
  2186                              <1> ;ret1:
  2187                              <1> 		; jmp ret / return to caller via 'ret'
  2188                              <1> 
  2189                              <1> rcvt:   ; < receive/read character from tty >
  2190                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2191                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2192                              <1> 	;
  2193                              <1> 	; Retro UNIX 8086 v1 modification !
  2194                              <1> 	; 
  2195                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2196                              <1> 	;		(exactly different than this one)
  2197                              <1> 	;	was in 'u9.s' file.
  2198                              <1> 	;
  2199 0000556F 2C0A                <1> 	sub 	al, 10
  2200                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2201                              <1> 	; 16/07/2013
  2202                              <1> 	; 21/05/2013
  2203 00005571 EBBC                <1>         jmp     short rttys
  2204                              <1>       
  2205                              <1> ;rppt: / read paper tape
  2206                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2207                              <1> ;			 / places
  2208                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2209                              <1> ;		       / also enables read bit in prs
  2210                              <1> ;	jsr	r0,passc / place character in users buffer area
  2211                              <1> ;	br	rppt
  2212                              <1> 
  2213                              <1> rmem: ; / transfer characters from memory to a user area of core
  2214                              <1> 	; 17/10/2015
  2215                              <1> 	; 11/06/2015
  2216                              <1> 	; 24/05/2015
  2217                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2218                              <1> 	;
  2219 00005573 8B35[18700000]      <1> 	mov     esi, [u.fofp]
  2220                              <1> rmem_1:
  2221 00005579 8B1E                <1>         mov     ebx, [esi]        
  2222                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2223                              <1> 		               ; / to be transferred to user
  2224 0000557B FF06                <1>         inc     dword [esi] ; 17/10/2015
  2225                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2226                              <1> 			    ; / char in memory file
  2227 0000557D 8A03                <1> 	mov	al, [ebx]
  2228                              <1> 		; movb (r1),r1 / get character from memory file, 
  2229                              <1> 		             ; / put it in r1
  2230 0000557F E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2231                              <1> 			     ;  / the next byte of the users core area
  2232                              <1> 		; br rmem / continue
  2233 00005584 75F3                <1> 	jnz	short rmem_1
  2234                              <1> ret_:
  2235 00005586 58                  <1> 	pop	eax ; 09/06/2015
  2236 00005587 C3                  <1> 	retn
  2237                              <1> 
  2238                              <1> rlpr:
  2239                              <1> ;1:
  2240                              <1> ;rcrd:
  2241 00005588 C705[5D700000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2241 00005590 0000                <1>
  2242 00005592 E9EEE6FFFF          <1> 	jmp	error
  2243                              <1> 		;jmp	error / see 'error' routine
  2244                              <1> 
  2245                              <1> dskr:
  2246                              <1> 	; 12/10/2015
  2247                              <1> 	; 21/08/2015
  2248                              <1> 	; 25/07/2015
  2249                              <1> 	; 10/07/2015
  2250                              <1> 	; 16/06/2015
  2251                              <1> 	; 31/05/2015
  2252                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2253                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2254                              <1> dskr_0:
  2255 00005597 50                  <1> 	push	eax
  2256                              <1> 		; mov (sp),r1 / i-number in r1
  2257                              <1> 	; AX = i-number
  2258 00005598 E82FFDFFFF          <1> 	call	iget
  2259                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2260 0000559D 0FB715[DA6C0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2261                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2262 000055A4 8B1D[18700000]      <1> 	mov	ebx, [u.fofp]
  2263 000055AA 2B13                <1> 	sub	edx, [ebx]
  2264                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2265                              <1>         ; 12/10/2015
  2266                              <1> 	; jna     short ret_ 
  2267                              <1> 		; blos ret
  2268 000055AC 7709                <1> 	ja	short dskr_1
  2269                              <1> 	;
  2270                              <1> dskr_retn: ; 12/10/2015
  2271 000055AE 58                  <1> 	pop	eax
  2272 000055AF C605[6F700000]00    <1> 	mov	byte [u.kcall], 0
  2273 000055B6 C3                  <1> 	retn	
  2274                              <1> dskr_1: 
  2275 000055B7 3B15[2C700000]      <1> 	cmp     edx, [u.count] 
  2276                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2277                              <1> 			       ; / to carry out read
  2278 000055BD 7306                <1> 	jnb	short dskr_2
  2279                              <1> 		; bhis 1f
  2280 000055BF 8915[2C700000]      <1> 	mov	[u.count], edx
  2281                              <1> 		; mov r2,u.count / no, just read to end of file
  2282                              <1> dskr_2: ; 1:
  2283                              <1> 	; AX = i-number
  2284 000055C5 E896FBFFFF          <1> 	call	mget
  2285                              <1> 		; jsr r0,mget / returns physical block number of block 
  2286                              <1> 			    ; / in file where offset points
  2287                              <1> 	; eAX = physical block number
  2288 000055CA E8B6070000          <1> 	call	dskrd
  2289                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2290                              <1> 			     ; / 1st word of data in buffer
  2291                              <1> 	; 09/06/2015
  2292 000055CF 803D[6F700000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2293 000055D6 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2294 000055D8 66833D[6D700000]00  <1> 	cmp	word [u.pcount], 0
  2295 000055E0 7705                <1> 	ja	short dskr_4
  2296                              <1> dskr_3:
  2297                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2298 000055E2 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2299                              <1> dskr_4:
  2300                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2301 000055E7 E8BD020000          <1> 	call	sioreg
  2302                              <1> 		; jsr r0,sioreg
  2303 000055EC 87F7                <1> 	xchg	esi, edi
  2304                              <1> 	; eDI = file (user data) offset
  2305                              <1> 	; eSI = sector (I/O) buffer offset
  2306                              <1> 	; eCX = byte count
  2307 000055EE F3A4                <1> 	rep	movsb
  2308                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2309                              <1> 		                 ; / starting at u.base
  2310                              <1> 		; dec r3
  2311                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2312                              <1> 	; 25/07/2015
  2313                              <1> 	; eax = remain bytes in buffer
  2314                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2315 000055F0 09C0                <1> 	or	eax, eax
  2316 000055F2 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2317                              <1> 	; 03/08/2013
  2318                              <1> 	;pop	eax
  2319 000055F4 390D[2C700000]      <1> 	cmp	[u.count], ecx ; 0
  2320                              <1> 		; tst u.count / all bytes read off disk
  2321                              <1> 		; bne dskr
  2322                              <1> 		; br ret
  2323                              <1>         ;ja      short dskr_0
  2324                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2325                              <1> 	;retn
  2326                              <1> 	; 12/10/2015
  2327 000055FA 76B2                <1> 	jna	short dskr_retn
  2328 000055FC 58                  <1> 	pop	eax  ; (i-node number)
  2329 000055FD EB98                <1> 	jmp	short dskr_0
  2330                              <1> 	
  2331                              <1> passc:
  2332                              <1> 	; 18/10/2015
  2333                              <1> 	; 10/07/2015
  2334                              <1> 	; 01/07/2015
  2335                              <1> 	; 08/06/2015
  2336                              <1> 	; 04/06/2015
  2337                              <1> 	; 20/05/2015
  2338                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2339                              <1> 	;
  2340                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2341                              <1> 	;		      to physical address
  2342 000055FF 66833D[6D700000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2343                              <1> 			     ; 1-4095 --> use previous physical base address
  2344                              <1> 			     ; in [u.pbase]
  2345 00005607 7705                <1> 	ja	short passc_3
  2346                              <1> 	; 08/06/2015 - 10/07/2015
  2347 00005609 E82C000000          <1> 	call	trans_addr_w
  2348                              <1> passc_3:
  2349                              <1> 	; 19/05/2015
  2350 0000560E 66FF0D[6D700000]    <1> 	dec	word [u.pcount]
  2351                              <1> 	;
  2352 00005615 8B1D[69700000]      <1> 	mov	ebx, [u.pbase]
  2353 0000561B 8803                <1> 	mov	[ebx], al
  2354                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2355                              <1> 		               ; / users buffer
  2356 0000561D FF05[28700000]      <1> 	inc	dword [u.base]
  2357                              <1> 		; inc u.base / increment the pointer to point to 
  2358                              <1> 			  ; / the next byte in users buffer
  2359 00005623 FF05[69700000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2360 00005629 FF05[30700000]      <1> 	inc	dword [u.nread]
  2361                              <1> 		; inc u.nread / increment the number of bytes read
  2362 0000562F FF0D[2C700000]      <1> 	dec	dword [u.count]
  2363                              <1> 		; dec u.count / decrement the number of bytes to be read
  2364                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2365 00005635 C3                  <1> 	retn
  2366                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2367                              <1> 		             ; / 'readi' by:
  2368                              <1> 		;/ (1) pop the return address off the stack into r0
  2369                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2370                              <1> 	;1:
  2371                              <1> 		; clr	*$ps / clear processor status
  2372                              <1> 		; rts r0 / return to address currently on top of stack
  2373                              <1> 
  2374                              <1> trans_addr_r:
  2375                              <1> 	; Translate virtual address to physical address 
  2376                              <1> 	; for reading from user's memory space
  2377                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2378                              <1> 	; 18/10/2015
  2379                              <1> 	; 10/07/2015
  2380                              <1> 	; 09/06/2015
  2381                              <1> 	; 08/06/2015 
  2382                              <1> 	; 04/06/2015
  2383                              <1> 	;
  2384                              <1> 	; 18/10/2015
  2385 00005636 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2386 00005638 EB04                <1> 	jmp 	short trans_addr_rw
  2387                              <1> 
  2388                              <1> 	;push	eax
  2389                              <1> 	;push	ebx
  2390                              <1> 	;mov	ebx, [u.base]
  2391                              <1> 	;call	get_physical_addr ; get physical address
  2392                              <1> 	;;jnc	short cpass_0
  2393                              <1> 	;jnc	short passc_1
  2394                              <1> 	;mov	[u.error], eax
  2395                              <1> 	;;pop	ebx
  2396                              <1> 	;;pop	eax
  2397                              <1> 	;jmp	error
  2398                              <1> ;cpass_0:
  2399                              <1> 	; 18/10/2015
  2400                              <1> 	; 20/05/2015
  2401                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2402                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2403                              <1> 	;pop	ebx
  2404                              <1> 	;pop	eax
  2405                              <1> 	;retn	; 08/06/2015
  2406                              <1> 
  2407                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2408                              <1> trans_addr_w:
  2409                              <1> 	; 31/12/2021
  2410                              <1> 	; Translate virtual address to physical address 
  2411                              <1> 	; for writing to user's memory space
  2412                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2413                              <1> 	; 18/10/2015
  2414                              <1> 	; 29/07/2015
  2415                              <1> 	; 10/07/2015
  2416                              <1> 	; 09/06/2015
  2417                              <1> 	; 08/06/2015
  2418                              <1> 	; 04/06/2015 (passc)
  2419                              <1> 	;
  2420                              <1> 	; 18/10/2015
  2421 0000563A 29D2                <1> 	sub	edx, edx
  2422 0000563C FEC2                <1> 	inc	dl ; 1 (write access sign)
  2423                              <1> trans_addr_rw:
  2424 0000563E 50                  <1> 	push	eax
  2425 0000563F 53                  <1> 	push	ebx
  2426                              <1> 	; 18/10/2015
  2427 00005640 52                  <1> 	push 	edx ; r/w sign (in DL)
  2428                              <1> 	;
  2429 00005641 8B1D[28700000]      <1> 	mov	ebx, [u.base]
  2430 00005647 E8DADCFFFF          <1> 	call	get_physical_addr ; get physical address
  2431 0000564C 730A                <1> 	jnc	short passc_0
  2432 0000564E A3[5D700000]        <1> 	mov	[u.error], eax
  2433                              <1> 	;pop	edx
  2434                              <1> 	;pop 	ebx
  2435                              <1> 	;pop	eax
  2436 00005653 E92DE6FFFF          <1> 	jmp	error
  2437                              <1> passc_0:
  2438 00005658 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2439 0000565B 5A                  <1> 	pop	edx ; 18/10/2015
  2440 0000565C 7517                <1> 	jnz	short passc_1
  2441                              <1> 	; 18/10/2015
  2442 0000565E 20D2                <1> 	and 	dl, dl
  2443 00005660 7413                <1> 	jz	short passc_1
  2444                              <1> 	; 20/05/2015
  2445                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2446                              <1> 	; EBX = linear address
  2447 00005662 51                  <1> 	push 	ecx
  2448 00005663 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2449 00005664 E82CDCFFFF          <1> 	call 	copy_page
  2450 00005669 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2451 0000566A 59                  <1> 	pop	ecx
  2452 0000566B 7217                <1> 	jc	short passc_2
  2453                              <1> 	; 24/12/2021
  2454                              <1> 	;push	eax ; physical address of the new/allocated page
  2455                              <1> 	;call	add_to_swap_queue
  2456                              <1> 	;pop	eax
  2457                              <1> 	; 18/10/2015
  2458 0000566D 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2459                              <1> 	;mov 	ecx, PAGE_SIZE
  2460                              <1> 	;sub	ecx, ebx 
  2461 00005673 01D8                <1> 	add	eax, ebx  
  2462                              <1> passc_1: 
  2463                              <1> 	; 18/10/2015
  2464                              <1> 	; 20/05/2015
  2465 00005675 A3[69700000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2466 0000567A 66890D[6D700000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2467 00005681 5B                  <1> 	pop	ebx
  2468 00005682 58                  <1> 	pop	eax
  2469 00005683 C3                  <1> 	retn	; 08/06/2015
  2470                              <1> passc_2:
  2471 00005684 C705[5D700000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2471 0000568C 0000                <1>
  2472                              <1> 	;pop 	ebx
  2473                              <1> 	;pop	eax
  2474 0000568E E9F2E5FFFF          <1> 	jmp	error
  2475                              <1> 
  2476                              <1> writei:
  2477                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2478                              <1> 	; 20/05/2015
  2479                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2480                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2481                              <1> 	;
  2482                              <1> 	; Write data to file with inode number in R1
  2483                              <1> 	; 
  2484                              <1> 	; INPUTS ->
  2485                              <1> 	;    r1 - inode number
  2486                              <1> 	;    u.count - byte count to be written
  2487                              <1> 	;    u.base - points to user buffer
  2488                              <1> 	;    u.fofp - points to word with current file offset
  2489                              <1> 	; OUTPUTS ->
  2490                              <1> 	;    u.count - cleared
  2491                              <1> 	;    u.nread - accumulates total bytes passed back	
  2492                              <1> 	; ((AX = R1))
  2493                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2494                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2495                              <1> 
  2496 00005693 31C9                <1> 	xor	ecx, ecx
  2497 00005695 890D[30700000]      <1> 	mov 	[u.nread], ecx  ; 0
  2498                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2499                              <1> 		            ; / read or write calls
  2500 0000569B 66890D[6D700000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2501 000056A2 390D[2C700000]      <1> 	cmp 	[u.count], ecx
  2502                              <1> 	;	; tst u.count / test the byte count specified by the user
  2503 000056A8 7701                <1> 	ja 	short writei_1 ; 1f
  2504                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2505 000056AA C3                  <1> 	retn
  2506                              <1> 	;	; rts r0 / no, return - no writing to do
  2507                              <1> writei_1: ;1:
  2508                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2509 000056AB 6683F828            <1> 	cmp 	ax, 40
  2510                              <1> 		; cmp r1,$40.
  2511                              <1> 		; / does the i-node number indicate a special file?
  2512                              <1> 	;ja	dskw 
  2513                              <1> 		; bgt dskw / no, branch to standard file output
  2514                              <1> 	; 24/12/2021
  2515 000056AF 7605                <1> 	jna	short writei_3
  2516 000056B1 E9EE000000          <1> 	jmp	dskw
  2517                              <1> writei_3:
  2518                              <1> 	; (20/05/2015)
  2519 000056B6 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2520 000056B7 0FB6D8              <1> 	movzx	ebx, al
  2521 000056BA 66C1E302            <1> 	shl	bx, 2
  2522                              <1> 		; asl r1 / yes, calculate the index into the special file
  2523 000056BE 81C3[C2560000]      <1> 	add	ebx, writei_2 - 4
  2524 000056C4 FF23                <1> 	jmp	dword [ebx]	
  2525                              <1> 		; jmp *1f-2(r1)
  2526                              <1> 		; / jump table and jump to the appropriate routine
  2527                              <1> writei_2: ;1:
  2528 000056C6 [12570000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2529                              <1> 		 ;wtty / tty; r1=2
  2530                              <1> 		 ;wppt / ppt; r1=4
  2531 000056CA [74570000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2532                              <1> 		 ;wmem / mem; r1=6
  2533                              <1> 		 ;wrf0 / rf0
  2534                              <1> 		 ;wrk0 / rk0
  2535                              <1> 		 ;wtap / tap0
  2536                              <1> 		 ;wtap / tap1
  2537                              <1> 		 ;wtap / tap2
  2538                              <1> 		 ;wtap / tap3
  2539                              <1> 		 ;wtap / tap4
  2540                              <1> 		 ;wtap / tap5
  2541                              <1> 		 ;wtap / tap6
  2542                              <1> 		 ;wtap / tap7
  2543 000056CE [AD5C0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2544 000056D2 [AD5C0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2545 000056D6 [AD5C0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2546 000056DA [AD5C0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2547 000056DE [AD5C0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2548 000056E2 [AD5C0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2549 000056E6 [65570000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2550 000056EA [5F570000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2551                              <1> 		 ;xmtt / tty0
  2552 000056EE [5F570000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2553                              <1> 		 ;xmtt / tty1
  2554 000056F2 [5F570000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2555                              <1> 		 ;xmtt / tty2
  2556 000056F6 [5F570000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2557                              <1> 		 ;xmtt / tty3
  2558 000056FA [5F570000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2559                              <1> 		 ;xmtt / tty4
  2560 000056FE [5F570000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2561                              <1> 		 ;xmtt / tty5
  2562 00005702 [5F570000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2563                              <1> 		 ;xmtt / tty6
  2564 00005706 [5F570000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2565                              <1> 		 ;xmtt / tty7
  2566 0000570A [5F570000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2567                              <1> 		; / wlpr / lpr
  2568 0000570E [5F570000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2569                              <1> 
  2570                              <1> wtty: ; write to console tty (write to screen)
  2571                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2572                              <1> 	; 18/11/2015
  2573                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2574                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2575                              <1> 	;
  2576                              <1> 	; Console tty output is on current video page
  2577                              <1> 	; Console tty character output procedure is changed here
  2578                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2579                              <1> 	;
  2580 00005712 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2581 00005719 8AA3[556D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2582 0000571F 88E0                <1> 	mov	al, ah ; 07/07/2014
  2583                              <1> wttys:	
  2584                              <1> 	; 10/10/2013
  2585 00005721 8825[5C700000]      <1> 	mov 	[u.ttyn], ah
  2586                              <1> 	; 13/01/2014
  2587 00005727 FEC0                <1> 	inc	al
  2588 00005729 A2[39700000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2589                              <1> wtty_nc: ; 15/05/2013
  2590                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2591 0000572E E816010000          <1> 	call	cpass
  2592                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2593                              <1> 		             ; / none go to return address in syswrite
  2594                              <1> 		; tst r1 / is character = null
  2595                              <1> 		; beq wtty / yes, get next character
  2596                              <1> 	; 10/10/2013
  2597 00005733 7428                <1> 	jz	short wret
  2598                              <1> 	;1 :
  2599                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2600                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2601                              <1> 		;	          / than 20
  2602                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2603                              <1> 	; 27/06/2014
  2604                              <1> wtty_1:
  2605                              <1> 	; AH = tty number
  2606                              <1> 	; AL = ASCII code of the character
  2607                              <1> 	; 15/04/2014
  2608                              <1> 	;push	ax
  2609                              <1> 	; 24/12/2021
  2610 00005735 50                  <1> 	push	eax
  2611 00005736 E8A1090000          <1> 	call	putc ; 14/05/2013
  2612 0000573B 731D                <1> 	jnc	short wtty_2
  2613                              <1> 	; 18/11/2015
  2614 0000573D E80BF9FFFF          <1> 	call	idle
  2615                              <1> 	;mov	ax, [esp]
  2616                              <1> 	; 24/12/2021
  2617 00005742 8B0424              <1> 	mov	eax, [esp]
  2618 00005745 E892090000          <1> 	call	putc
  2619 0000574A 730E                <1> 	jnc	short wtty_2 
  2620                              <1> 	; 02/06/2014
  2621 0000574C 8A25[5C700000]      <1> 	mov	ah, [u.ttyn]
  2622 00005752 E889F9FFFF          <1> 	call	sleep
  2623                              <1> 	;pop	ax
  2624                              <1> 	; 24/12/5021
  2625 00005757 58                  <1> 	pop	eax
  2626 00005758 EBDB                <1> 	jmp 	short wtty_1
  2627                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2628                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2629                              <1> 			      ; / console tty and
  2630                              <1> 		; br 	2f / place character in list; if none available
  2631                              <1> 		   	  ; / branch to put process to sleep
  2632                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2633                              <1> wtty_2:
  2634                              <1> 	; 15/04/2014
  2635                              <1> 	;pop	ax
  2636                              <1> 	; 24/12/2021
  2637 0000575A 58                  <1> 	pop	eax
  2638 0000575B EBD1                <1> 	jmp	short wtty_nc
  2639                              <1> 		; br wtty
  2640                              <1> wret:	; 10/10/2013 (20/05/2015)
  2641 0000575D 58                  <1> 	pop	eax
  2642 0000575E C3                  <1> 	retn
  2643                              <1> 	;2:
  2644                              <1> 		;mov	r1,-(sp) / place character on stack
  2645                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2646                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2647                              <1> 		;br	1b / try again to place character in clist and output
  2648                              <1> 
  2649                              <1> xmtt:   ; < send/write character to tty >
  2650                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2651                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2652                              <1> 	;
  2653                              <1> 	; Retro UNIX 8086 v1 modification !
  2654                              <1> 	; 
  2655                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2656                              <1> 	;		(exactly different than this one)
  2657                              <1> 	;	was in 'u9.s' file.
  2658                              <1> 	;
  2659 0000575F 2C0A                <1> 	sub 	al, 10
  2660                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2661                              <1> 	 ; 10/10/2013
  2662 00005761 88C4                <1> 	mov	ah, al
  2663                              <1> 	; 28/07/2013
  2664 00005763 EBBC                <1> 	jmp	short wttys
  2665                              <1> 
  2666                              <1> ;wppt:
  2667                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2668                              <1> ;		         / if none return to writei's calling routine
  2669                              <1> ;	jsr	r0,pptoc / output character on ppt
  2670                              <1> ;	br	wppt
  2671                              <1> wlpr:
  2672 00005765 C705[5D700000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2672 0000576D 0000                <1>
  2673 0000576F E911E5FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2674                              <1> 		;/	jsr	r0,cpass
  2675                              <1> 		;/	cmp	r0,$'a
  2676                              <1> 		;/	blo	1f
  2677                              <1> 		;/	cmp	r1,$'z
  2678                              <1> 		;/	bhi	1f
  2679                              <1> 		;/	sub	$40,r1
  2680                              <1> 		;/1:
  2681                              <1> 		;/	jsr	r0,lptoc
  2682                              <1> 		;/	br	wlpr
  2683                              <1> 		; br rmem / continue
  2684                              <1> 
  2685                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2686                              <1> 	; 17/10/2015
  2687                              <1> 	; 11/06/2015
  2688                              <1> 	; 24/05/2015
  2689                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2690                              <1> 	;
  2691 00005774 813D[D5070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2691 0000577A [70500000]          <1>
  2692 0000577E 7415                <1>         je      short wmem_acc_err
  2693                              <1> 	;
  2694 00005780 8B35[18700000]      <1>         mov     esi, [u.fofp] 
  2695                              <1> wmem_1:
  2696 00005786 E8BE000000          <1> 	call	cpass
  2697                              <1> 		; jsr r0,cpass / get next character from users area of
  2698                              <1> 			     ; / core and put it in r1
  2699                              <1>         	; mov r1,-(sp) / put character on the stack
  2700                              <1> 	; 20/09/2013
  2701 0000578B 74D0                <1> 	jz	short wret ; wmem_2  
  2702 0000578D 8B1E                <1>         mov     ebx, [esi]
  2703                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2704 0000578F FF06                <1>         inc     dword [esi] ; 17/10/2015
  2705                              <1> 		; inc *u.fofp / increment file offset to point to next
  2706                              <1> 			    ; / available location in file
  2707 00005791 8803                <1> 	mov	[ebx], al	
  2708                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2709                              <1> 			        ; / assigned to it
  2710 00005793 EBF1                <1> 	jmp	short wmem_1
  2711                              <1> 		; br wmem / continue
  2712                              <1> 	;1:
  2713                              <1> 	;jmp	error / ?
  2714                              <1> ;wmem_2:	
  2715                              <1> ;	; 20/09/2013
  2716                              <1> ;	pop	ax
  2717                              <1> ;	retn
  2718                              <1> 
  2719                              <1> wmem_acc_err:
  2720 00005795 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2720 0000579D 0000                <1>
  2721 0000579F E9E1E4FFFF          <1> 	jmp	error
  2722                              <1> 
  2723                              <1> 
  2724                              <1> dskw: ; / write routine for non-special files
  2725                              <1> 	;
  2726                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2727                              <1> 	; 25/07/2015
  2728                              <1> 	; 16/06/2015
  2729                              <1> 	; 09/06/2015
  2730                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2731                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2732                              <1> 	;
  2733                              <1> 	; 01/08/2013 (mkdir_w check)
  2734                              <1> 	;push	ax ; 26/04/2013
  2735                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2736                              <1> 	; 24/12/2021
  2737 000057A4 50                  <1> 	push	eax
  2738                              <1> 	; AX = inode number
  2739 000057A5 E822FBFFFF          <1> 	call	iget
  2740                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2741                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2742 000057AA 8B1D[18700000]      <1>         mov     ebx, [u.fofp] 
  2743 000057B0 8B13                <1> 	mov 	edx, [ebx]
  2744                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2745                              <1> 			       ; / in the fsp entry for this file] in r2
  2746 000057B2 0315[2C700000]      <1> 	add 	edx, [u.count]	
  2747                              <1> 		; add u.count,r2 / no. of bytes to be written
  2748                              <1> 			       ; / + file offset is put in r2
  2749                              <1> 	; 16/06/2015        
  2750 000057B8 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2751 000057BE 760F                <1> 	jna	short dskw_0
  2752 000057C0 C705[5D700000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2752 000057C8 0000                <1>
  2753 000057CA E9B6E4FFFF          <1> 	jmp	error
  2754                              <1> dskw_0:	
  2755 000057CF 663B15[DA6C0000]    <1> 	cmp     dx, [i.size]
  2756                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2757                              <1> 		              ; / the file?
  2758 000057D6 760C                <1> 	jna	short dskw_1
  2759                              <1> 		; blos 1f / no, branch
  2760 000057D8 668915[DA6C0000]    <1>         mov     [i.size], dx
  2761                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2762                              <1> 			      ; / file offset + no. of data bytes
  2763 000057DF E8F4FBFFFF          <1> 	call	setimod
  2764                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2765                              <1> 		          ; / modified), stuff time of modification into
  2766                              <1> 	          	  ; / core image of i-node
  2767                              <1> dskw_1: ; 1:	
  2768 000057E4 E877F9FFFF          <1> 	call	mget
  2769                              <1> 	; eAX = Block number
  2770                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2771                              <1> 			    ; /	the next data byte
  2772                              <1> 	; eax = block number
  2773 000057E9 8B1D[18700000]      <1> 	mov     ebx, [u.fofp]
  2774 000057EF 8B13                <1> 	mov	edx, [ebx]
  2775 000057F1 81E2FF010000        <1> 	and	edx, 1FFh  
  2776                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2777 000057F7 750C                <1> 	jnz	short dskw_2
  2778                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2779                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2780 000057F9 813D[2C700000]0002- <1> 	cmp	dword [u.count], 512
  2780 00005801 0000                <1>
  2781                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2782                              <1> 				  ; / an entire block? (i.e., no. of
  2783 00005803 7305                <1> 	jnb	short dskw_3
  2784                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2785                              <1> 			; / Yes, branch. Don't have to read block
  2786                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2787                              <1>    		; / overwritten).
  2788 00005805 E87B050000          <1> 	call	dskrd
  2789                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2790                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2791                              <1> dskw_3: ; 3:
  2792                              <1> 	; eAX (r1) = block/sector number
  2793 0000580A E8D6050000          <1> 	call	wslot
  2794                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2795                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2796 0000580F 803D[6F700000]00    <1> 	cmp	byte [u.kcall], 0
  2797 00005816 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2798                              <1> 	;
  2799 00005818 66833D[6D700000]00  <1> 	cmp	word [u.pcount], 0
  2800 00005820 7705                <1> 	ja	short dskw_5
  2801                              <1> dskw_4:
  2802                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2803 00005822 E80FFEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2804                              <1> dskw_5:
  2805                              <1> 	; eBX (r5) = system (I/O) buffer address
  2806 00005827 E87D000000          <1> 	call	sioreg
  2807                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2808                              <1> 			     ; / r1 = address of data, r2 points to location
  2809                              <1> 			     ; / in buffer in which to start writing data
  2810                              <1> 	; eSI = file (user data) offset
  2811                              <1> 	; eDI = sector (I/O) buffer offset
  2812                              <1> 	; eCX = byte count
  2813                              <1> 	;
  2814 0000582C F3A4                <1>   	rep	movsb
  2815                              <1> 		; movb (r1 )+,(r2)+ 
  2816                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2817                              <1> 		; dec r3 / decrement no. of bytes to be written
  2818                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2819                              <1> 	; 25/07/2015
  2820                              <1> 	; eax = remain bytes in buffer
  2821                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2822 0000582E 09C0                <1> 	or	eax, eax
  2823 00005830 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2824                              <1> dskw_6:
  2825 00005832 E8CA050000          <1> 	call	dskwr
  2826                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2827 00005837 833D[2C700000]00    <1>         cmp     dword [u.count], 0
  2828                              <1> 		; tst u.count / any more data to write?
  2829 0000583E 77A4                <1> 	ja	short dskw_1
  2830                              <1> 		; bne 1b / yes, branch
  2831                              <1> 	; 03/08/2013
  2832 00005840 C605[6F700000]00    <1> 	mov	byte [u.kcall], 0
  2833                              <1> 	; 20/09/2013 (;;)
  2834                              <1> 	;pop	ax
  2835                              <1> 	; 24/12/2021
  2836 00005847 58                  <1> 	pop	eax
  2837 00005848 C3                  <1> 	retn
  2838                              <1> 	;;jmp 	short dskw_ret 
  2839                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2840                              <1> 
  2841                              <1> cpass: ; / get next character from user area of core and put it in r1
  2842                              <1> 	; 18/10/2015
  2843                              <1> 	; 10/10/2015
  2844                              <1> 	; 10/07/2015
  2845                              <1> 	; 02/07/2015
  2846                              <1> 	; 01/07/2015
  2847                              <1> 	; 24/06/2015
  2848                              <1> 	; 08/06/2015
  2849                              <1> 	; 04/06/2015
  2850                              <1> 	; 20/05/2015
  2851                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2852                              <1> 	;
  2853                              <1> 	; INPUTS -> 
  2854                              <1> 	;     [u.base] = virtual address in user area
  2855                              <1> 	;     [u.count] = byte count (max.)
  2856                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2857                              <1> 	; OUTPUTS -> 
  2858                              <1> 	;     AL = the character which is pointed by [u.base]
  2859                              <1> 	;     zf = 1 -> transfer count has been completed	
  2860                              <1>         ;
  2861                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  2862                              <1> 	;
  2863                              <1> 	;
  2864 00005849 833D[2C700000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2865                              <1> 		; tst u.count / have all the characters been transferred
  2866                              <1> 			    ; / (i.e., u.count, # of chars. left
  2867 00005850 763F                <1> 	jna	short cpass_3
  2868                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2869 00005852 FF0D[2C700000]      <1> 	dec	dword [u.count]
  2870                              <1> 		; dec u.count / no, decrement u.count
  2871                              <1>         ; 19/05/2015 
  2872                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2873                              <1> 	;		      to physical address
  2874 00005858 66833D[6D700000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2875                              <1> 			     ; 1-4095 --> use previous physical base address
  2876                              <1> 			     ; in [u.pbase]
  2877 00005860 770E                <1> 	ja	short cpass_1
  2878                              <1> 	; 02/07/2015
  2879 00005862 833D[65700000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  2880 00005869 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  2881                              <1> 	; 08/06/2015 - 10/07/2015
  2882 0000586B E8C6FDFFFF          <1> 	call	trans_addr_r
  2883                              <1> cpass_1:
  2884                              <1> 	; 02/07/2015
  2885                              <1> 	; 24/06/2015
  2886 00005870 66FF0D[6D700000]    <1> 	dec	word [u.pcount]
  2887                              <1> cpass_2: 
  2888                              <1> 	 ;10/10/2015
  2889                              <1> 	; 02/07/2015
  2890 00005877 8B15[69700000]      <1> 	mov	edx, [u.pbase]
  2891 0000587D 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  2892                              <1> 		; movb *u.base,r1 / take the character pointed to 
  2893                              <1> 				; / by u.base and put it in r1
  2894 0000587F FF05[30700000]      <1> 	inc	dword [u.nread]
  2895                              <1> 		; inc u.nread / increment no. of bytes transferred
  2896 00005885 FF05[28700000]      <1> 	inc	dword [u.base]
  2897                              <1> 		; inc u.base / increment the buffer address to point to the
  2898                              <1> 			   ; / next byte
  2899 0000588B FF05[69700000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2900                              <1> cpass_3:
  2901 00005891 C3                  <1> 	retn
  2902                              <1> 		; rts	r0 / next byte
  2903                              <1> 	; 1: 
  2904                              <1> 		; mov (sp)+,r0 
  2905                              <1> 		         ; / put return address of calling routine into r0
  2906                              <1> 		; mov (sp)+,r1 / i-number in r1
  2907                              <1> 		; rts r0 / non-local return
  2908                              <1> cpass_k:
  2909                              <1> 	; 02/07/2015
  2910                              <1> 	; The caller is os kernel 
  2911                              <1> 	; (get sysexec arguments from kernel's memory space)
  2912                              <1> 	;
  2913 00005892 8B1D[28700000]      <1> 	mov	ebx, [u.base]
  2914 00005898 66C705[6D700000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  2914 000058A0 10                  <1>
  2915 000058A1 891D[69700000]      <1> 	mov	[u.pbase], ebx
  2916 000058A7 EBCE                <1> 	jmp	short cpass_2
  2917                              <1> 	
  2918                              <1> sioreg: 
  2919                              <1> 	; 25/07/2015
  2920                              <1> 	; 18/07/2015
  2921                              <1> 	; 02/07/2015
  2922                              <1> 	; 17/06/2015
  2923                              <1> 	; 09/06/2015
  2924                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2925                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  2926                              <1> 	;
  2927                              <1> 	; INPUTS -> 
  2928                              <1> 	;     eBX = system buffer (data) address (r5)
  2929                              <1> 	;     [u.fofp] = pointer to file offset pointer
  2930                              <1> 	;     [u.base] = virtual address of the user buffer
  2931                              <1> 	;     [u.pbase] = physical address of the user buffer
  2932                              <1> 	;     [u.count] = byte count
  2933                              <1> 	;     [u.pcount] = byte count within page frame 			
  2934                              <1> 	; OUTPUTS -> 
  2935                              <1> 	;     eSI = user data offset (r1)
  2936                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  2937                              <1> 	;     eCX = byte count (r3)
  2938                              <1> 	;     EAX = remain bytes after byte count within page frame
  2939                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  2940                              <1>         ;
  2941                              <1> 	; ((Modified registers:  EDX))
  2942                              <1>  
  2943 000058A9 8B35[18700000]      <1>         mov     esi, [u.fofp]
  2944 000058AF 8B3E                <1>         mov     edi, [esi]
  2945                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  2946 000058B1 89F9                <1> 	mov	ecx, edi
  2947                              <1> 		; mov r2,r3 / and also to r3
  2948 000058B3 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  2949                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  2950 000058B9 81E7FF010000        <1> 	and	edi, 1FFh
  2951                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  2952 000058BF 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  2953                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  2954                              <1> 			  ; / where data is to be placed
  2955                              <1>                 ; mov u.base,r1 / address of data is in r1
  2956 000058C1 F7D9                <1> 	neg	ecx
  2957                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  2958                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  2959 000058C3 3B0D[2C700000]      <1> 	cmp	ecx, [u.count]
  2960                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  2961                              <1> 			       ; / to be written to the file
  2962 000058C9 7606                <1> 	jna	short sioreg_0
  2963                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  2964                              <1> 			 ; / in the file block as the number to be written
  2965 000058CB 8B0D[2C700000]      <1> 	mov	ecx, [u.count]
  2966                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  2967                              <1> 			       ; / bytes as the number to be written
  2968                              <1> sioreg_0:
  2969                              <1> 	; 17/06/2015
  2970 000058D1 803D[6F700000]00    <1> 	cmp	byte [u.kcall], 0 
  2971 000058D8 7613                <1> 	jna	short sioreg_1
  2972                              <1> 	; 25/07/2015
  2973                              <1> 	 ; the caller is 'mkdir' or 'namei'
  2974 000058DA A1[28700000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  2975 000058DF A3[69700000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  2976 000058E4 66890D[6D700000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  2977 000058EB EB0B                <1> 	jmp	short sioreg_2
  2978                              <1> sioreg_1:
  2979                              <1> 	; 25/07/2015
  2980                              <1> 	; 18/07/2015
  2981                              <1> 	; 09/06/2015 
  2982 000058ED 0FB715[6D700000]    <1> 	movzx	edx, word [u.pcount]
  2983                              <1> 		; ecx and [u.pcount] are always > 0, here
  2984 000058F4 39D1                <1> 	cmp	ecx, edx	
  2985 000058F6 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  2986                              <1> sioreg_2: ; 2:
  2987 000058F8 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  2988                              <1> sioreg_3:
  2989 000058FA 010D[30700000]      <1> 	add 	[u.nread], ecx
  2990                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  2991                              <1> 			         ; / during write is put into u.nread
  2992 00005900 290D[2C700000]      <1> 	sub 	[u.count], ecx
  2993                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  2994                              <1> 			       ; / must be written or read
  2995 00005906 010D[28700000]      <1> 	add 	[u.base], ecx
  2996                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  2997                              <1> 			      ; / data bytes
  2998 0000590C 010E                <1>         add 	[esi], ecx 
  2999                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3000                              <1> 			       ; / + old file offset
  3001                              <1> 	; 25/07/2015
  3002 0000590E 8B35[69700000]      <1> 	mov	esi, [u.pbase]
  3003 00005914 66290D[6D700000]    <1> 	sub	[u.pcount], cx
  3004 0000591B 010D[69700000]      <1> 	add	[u.pbase], ecx
  3005 00005921 C3                  <1>         retn
  3006                              <1> 		; rts r0
  3007                              <1> 		; transfer count > [u.pcount]
  3008                              <1> sioreg_4:
  3009                              <1> 	; 25/07/2015
  3010                              <1> 	; transfer count > [u.pcount] 
  3011                              <1> 	; (ecx > edx)
  3012 00005922 89C8                <1> 	mov	eax, ecx
  3013 00005924 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3014 00005926 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3015 00005928 EBD0                <1> 	jmp	short sioreg_3
  1999                                  %include 'u7.s'        ; 18/04/2015
  2000                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC
  2001                              <1> ; Last Modification: 14/11/2015
  2002                              <1> ; ----------------------------------------------------------------------------
  2003                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2004                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2005                              <1> ;
  2006                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2007                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2008                              <1> ; <Bell Laboratories (17/3/1972)>
  2009                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2010                              <1> ;
  2011                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2012                              <1> ;
  2013                              <1> ; ****************************************************************************
  2014                              <1> 
  2015                              <1> sysmount: ; / mount file system; args special; name
  2016                              <1> 	; 14/11/2015
  2017                              <1> 	; 24/10/2015
  2018                              <1> 	; 13/10/2015
  2019                              <1> 	; 10/07/2015
  2020                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2021                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2022                              <1> 	;
  2023                              <1> 	; 'sysmount' anounces to the system that a removable 
  2024                              <1> 	; file system has been mounted on a special file.
  2025                              <1> 	; The device number of the special file is obtained via
  2026                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2027                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2028                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2029                              <1> 	; to read file system into core, i.e. the first block on the
  2030                              <1> 	; mountable file system is read in. This block is super block
  2031                              <1> 	; for the file system. This call is super user restricted.	
  2032                              <1> 	;
  2033                              <1> 	; Calling sequence:
  2034                              <1> 	;	sysmount; special; name
  2035                              <1> 	; Arguments:
  2036                              <1> 	;	special - pointer to name of special file (device)
  2037                              <1> 	;	name -  pointer to name of the root directory of the
  2038                              <1> 	;		newly mounted file system. 'name' should 
  2039                              <1> 	;		always be a directory.
  2040                              <1> 	; Inputs: - 
  2041                              <1> 	; Outputs: -
  2042                              <1> 	; ...............................................................
  2043                              <1> 	;				
  2044                              <1> 	; Retro UNIX 8086 v1 modification: 
  2045                              <1> 	;       'sysmount' system call has two arguments; so,
  2046                              <1> 	;	* 1st argument, special is pointed to by BX register
  2047                              <1> 	;	* 2nd argument, name is in CX register
  2048                              <1> 	;
  2049                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2050                              <1> 	;	       already modified for IBM PC compatibility and 
  2051                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2052                              <1> 	
  2053                              <1> 	;call	arg2
  2054                              <1> 		; jsr r0,arg2 / get arguments special and name
  2055 0000592A 891D[20700000]      <1> 	mov	[u.namep], ebx
  2056 00005930 51                  <1> 	push	ecx ; directory name
  2057 00005931 66833D[F46F0000]00  <1> 	cmp	word [mnti], 0
  2058                              <1> 		; tst mnti / is the i-number of the cross device file
  2059                              <1> 			 ; / zero?
  2060                              <1> 	;ja	error
  2061                              <1>         	; bne errora / no, error
  2062 00005939 0F87E9000000        <1> 	ja	sysmnt_err0
  2063                              <1> 	;
  2064 0000593F E8CC000000          <1> 	call	getspl
  2065                              <1> 		; jsr r0,getspl / get special files device number in r1
  2066                              <1> 	; 13/10/2015
  2067 00005944 0FB7D8              <1> 	movzx	ebx, ax ; ; Retro UNIX 8086 v1 device number (0 to 5)
  2068 00005947 F683[2A670000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2069 0000594E 750F                <1> 	jnz	short sysmnt_1
  2070                              <1> sysmnt_err1:
  2071 00005950 C705[5D700000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2071 00005958 0000                <1>
  2072 0000595A E926E3FFFF          <1> 	jmp	error
  2073                              <1> sysmnt_1:
  2074 0000595F 8F05[20700000]      <1> 	pop	dword [u.namep]
  2075                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2076                              <1> 				  ; / on the device
  2077                              <1> 	; 14/11/2015
  2078 00005965 53                  <1> 	push	ebx ; 13/10/2015
  2079                              <1> 		; mov r1,-(sp) / save the device number
  2080                              <1>         ;
  2081 00005966 E88CF1FFFF          <1> 	call	namei
  2082                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2083                              <1> 		       ; ax = 0 -> file not found 	
  2084                              <1> 	;jz	error
  2085                              <1> 	;jc	error
  2086                              <1> 		; jsr r0,namei / get the i-number of the file
  2087                              <1>                	; br errora
  2088 0000596B 730F                <1> 	jnc	short sysmnt_2
  2089                              <1> sysmnt_err2:
  2090 0000596D C705[5D700000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2090 00005975 0000                <1>
  2091 00005977 E909E3FFFF          <1> 	jmp	error
  2092                              <1> sysmnt_2:	
  2093 0000597C 66A3[F46F0000]      <1> 	mov	[mnti], ax
  2094                              <1>         	; mov r1,mnti / put it in mnti
  2095                              <1> ;	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2096                              <1> sysmnt_3: ;1:
  2097                              <1>         ;cmp	byte [ebx+1], 0
  2098                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2099                              <1> 			   ; / dismountable device set?
  2100                              <1>         ;jna	short sysmnt_4		
  2101                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2102                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2103                              <1> 	;jmp	short sysmnt_3
  2104                              <1> sysmnt_4:   
  2105 00005982 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2106 00005983 A2[F16F0000]        <1> 	mov	[mdev], al
  2107                              <1> 		; mov  (sp),mntd / no, put the device number in mntd
  2108 00005988 8803                <1> 	mov	[ebx], al
  2109                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2110                              <1> 			      ; / of the I/O queue entry
  2111                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2112                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2113 0000598A 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2114                              <1> 		; bis $2000,sb1 / set the read bit
  2115                              <1> 	; Retro UNIX 386 v1 modification : 
  2116                              <1> 	;	32 bit block number at buffer header offset 4
  2117 0000598F C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2118 00005996 E8A1050000          <1> 	call 	diskio
  2119 0000599B 731C                <1> 	jnc	short sysmnt_5
  2120 0000599D 31C0                <1> 	xor 	eax, eax
  2121 0000599F 66A3[F46F0000]      <1> 	mov	[mnti], ax ; 0
  2122 000059A5 A2[F16F0000]        <1> 	mov	[mdev], al ; 0
  2123                              <1> 	;mov	[cdev], al ; 0
  2124                              <1> sysmnt_invd:
  2125                              <1> 	; 14/11/2015
  2126 000059AA FEC8                <1> 	dec 	al
  2127 000059AC 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2128 000059AE FEC0                <1> 	inc	al
  2129 000059B0 48                  <1> 	dec	eax
  2130 000059B1 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2131 000059B4 E9CCE2FFFF          <1> 	jmp	error
  2132                              <1> sysmnt_5:
  2133                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2134                              <1> 	; (Following check is needed to prevent mounting an
  2135                              <1> 	; in valid valid file system (in valid super block).
  2136                              <1> 	; 
  2137 000059B9 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2138 000059BC C0E002              <1> 	shl	al, 2 ; 4*index
  2139 000059BF 8B88[0E670000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2140 000059C5 C1E103              <1> 	shl 	ecx, 3
  2141 000059C8 0FB715[CC7E0000]    <1> 	movzx	edx, word [sb1+4] ; the 1st data word
  2142 000059CF 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2143                              <1> 			 ; (in sectors), if they are not equal
  2144                              <1> 			 ; the disk to be mounted is an...	
  2145 000059D1 75D7                <1> 	jne	short sysmnt_invd ; invalid disk !
  2146                              <1> 			 ; (which has not got a valid super block)
  2147                              <1> 	;
  2148 000059D3 C6430100            <1> 	mov	byte [ebx+1], 0
  2149                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2150                              <1> ;sysmnt_6: ;1:
  2151                              <1> 	;;cmp	byte [sb1+1], 0
  2152                              <1> 		; tstb   sb1+1 / done reading?
  2153                              <1>    	;;jna	sysret
  2154                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2155                              <1> 	;;jmp	short sysmnt_6
  2156                              <1> 		;bne 1b / no, wait
  2157                              <1>         	;br sysreta / yes
  2158 000059D7 E9C9E2FFFF          <1> 	jmp	sysret
  2159                              <1> 
  2160                              <1> sysumount: ; / special dismount file system
  2161                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2162                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2163                              <1> 	;
  2164                              <1> 	; 04/11/2013
  2165                              <1> 	; 09/07/2013
  2166                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2167                              <1> 	; indicated as an argument is no longer contain a removable
  2168                              <1> 	; file system. 'getspl' gets the device number of the special
  2169                              <1> 	; file. If no file system was mounted on that device an error
  2170                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2171                              <1> 	; to 'sysret'.
  2172                              <1> 	;
  2173                              <1> 	; Calling sequence:
  2174                              <1> 	;	sysmount; special
  2175                              <1> 	; Arguments:
  2176                              <1> 	;	special - special file to dismount (device)
  2177                              <1> 	;
  2178                              <1> 	; Inputs: - 
  2179                              <1> 	; Outputs: -
  2180                              <1> 	; ...............................................................
  2181                              <1> 	;				
  2182                              <1> 	; Retro UNIX 8086 v1 modification: 
  2183                              <1> 	;       'sysumount' system call has one argument; so,
  2184                              <1> 	;	* Single argument, special is pointed to by BX register
  2185                              <1> 	;
  2186                              <1> 	
  2187                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2188                              <1> 	;call	arg
  2189                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2190 000059DC 891D[20700000]      <1>         mov	[u.namep], ebx
  2191 000059E2 E829000000          <1> 	call	getspl
  2192                              <1> 		; jsr r0,getspl / get the device number in r1
  2193 000059E7 3A05[F16F0000]      <1> 	cmp	al, [mdev]
  2194                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2195 000059ED 7539                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2196                              <1> 	;jne	error
  2197                              <1>         	; bne errora / no error
  2198 000059EF 30C0                <1> 	xor	al, al ; ah = 0
  2199                              <1> sysumnt_0: ;1:
  2200 000059F1 3805[C97E0000]      <1>      	cmp 	[sb1+1], al ; 0
  2201                              <1> 		; tstb sb1+1 / yes, is the device still doing I/O 
  2202                              <1> 			   ; / (inhibit bit set)?
  2203 000059F7 7607                <1> 	jna	short sysumnt_1		
  2204                              <1> 		; bne 1b / yes, wait
  2205 000059F9 E84FF6FFFF          <1> 	call	idle ; (wait for hardware interrupt)
  2206 000059FE EBF1                <1> 	jmp	short sysumnt_0
  2207                              <1> sysumnt_1:        
  2208 00005A00 A2[F16F0000]        <1> 	mov	[mdev], al
  2209                              <1> 	     	; clr mntd / no, clear these
  2210 00005A05 66A3[F46F0000]      <1>    	mov	[mnti], ax
  2211                              <1>         	; clr mnti
  2212 00005A0B E995E2FFFF          <1>         jmp	sysret
  2213                              <1> 		; br sysreta / return
  2214                              <1> 
  2215                              <1> getspl: ; / get device number from a special file name
  2216 00005A10 E8E2F0FFFF          <1> 	call	namei
  2217                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2218                              <1> 		       ; ax = 0 -> file not found 	
  2219 00005A15 0F8252FFFFFF        <1>         jc      sysmnt_err2 ; 'file not found !' error
  2220                              <1> 	;jz	error
  2221                              <1> 	;jc	error
  2222                              <1> 		; jsr r0,namei / get the i-number of the special file
  2223                              <1>                 ; br errora / no such file
  2224 00005A1B 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2225                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2226                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2227 00005A1F 7207                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2228                              <1> 	;jc	error
  2229                              <1> 		; ble errora / less than 0?  yes, error
  2230 00005A21 6683F805            <1>         cmp	ax, 5 ;
  2231                              <1> 		; cmp  r1,$9. / greater than 9  tap 7
  2232 00005A25 7701                <1> 	ja	short sysmnt_err0 ; 'permission denied !' error
  2233                              <1> 	;ja	error
  2234                              <1>         	; bgt errora / yes, error
  2235                              <1>         ; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2236                              <1> iopen_retn:
  2237 00005A27 C3                  <1> 	retn
  2238                              <1> 		; rts    r0 / return with device number in r1
  2239                              <1> sysmnt_err0:
  2240 00005A28 C705[5D700000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2240 00005A30 0000                <1>
  2241 00005A32 E94EE2FFFF          <1> 	jmp	error
  2242                              <1> iopen:
  2243                              <1> 	; 19/05/2015
  2244                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2245                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2246                              <1> 	;
  2247                              <1> 	; open file whose i-number is in r1
  2248                              <1> 	; 
  2249                              <1> 	; INPUTS ->
  2250                              <1> 	;    r1 - inode number
  2251                              <1> 	; OUTPUTS ->
  2252                              <1> 	;    file's inode in core	
  2253                              <1> 	;    r1 - inode number (positive)
  2254                              <1> 	;
  2255                              <1> 	; ((AX = R1))
  2256                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2257                              <1> 	;        
  2258                              <1> ; / open file whose i-number is in r1
  2259 00005A37 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2260                              <1> 		;tst r1 / write or read access?
  2261 00005A3A 756A                <1>         jnz	short iopen_2
  2262                              <1> 		;blt 2f / write, go to 2f
  2263 00005A3C B202                <1> 	mov	dl, 2 ; read access
  2264 00005A3E E85FF9FFFF          <1> 	call	access
  2265                              <1>         	; jsr r0,access; 2 
  2266                              <1> 	; / get inode into core with read access
  2267                              <1> 	; DL=2
  2268                              <1> iopen_0:
  2269 00005A43 6683F828            <1>         cmp	ax, 40
  2270                              <1> 		; cmp r1,$40. / is it a special file
  2271 00005A47 77DE                <1>         ja	short iopen_retn
  2272                              <1> 		;bgt  3f / no. 3f
  2273 00005A49 6650                <1> 	push	ax
  2274                              <1> 		; mov r1,-(sp) / yes, figure out
  2275 00005A4B 0FB6D8              <1> 	movzx	ebx, al
  2276 00005A4E 66C1E302            <1> 	shl	bx, 2
  2277                              <1> 		; asl r1
  2278 00005A52 81C3[565A0000]      <1>         add     ebx, iopen_1 - 4
  2279 00005A58 FF23                <1> 	jmp	dword [ebx]
  2280                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2281                              <1> iopen_1: ; 1:
  2282 00005A5A [C05A0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2283                              <1>  		 ;otty / tty ; r1=2
  2284                              <1>         	 ;oppt / ppt ; r1=4
  2285 00005A5E [5D5B0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2286                              <1> 		 ;sret / mem ; r1=6
  2287                              <1> 		 ;sret / rf0
  2288                              <1>         	 ;sret / rk0
  2289                              <1>         	 ;sret / tap0
  2290                              <1>         	 ;sret / tap1
  2291                              <1>         	 ;sret / tap2
  2292                              <1>         	 ;sret / tap3
  2293                              <1>         	 ;sret / tap4
  2294                              <1>         	 ;sret / tap5
  2295                              <1>         	 ;sret / tap6
  2296                              <1>         	 ;sret / tap7
  2297 00005A62 [5D5B0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2298 00005A66 [5D5B0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2299 00005A6A [5D5B0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2300 00005A6E [5D5B0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2301 00005A72 [5D5B0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2302 00005A76 [5D5B0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2303                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2304 00005A7A [5D5B0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2305 00005A7E [CF5A0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2306                              <1> 		 ;ocvt / tty0
  2307 00005A82 [CF5A0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2308                              <1> 		 ;ocvt / tty1
  2309 00005A86 [CF5A0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2310                              <1> 		 ;ocvt / tty2
  2311 00005A8A [CF5A0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2312                              <1> 		 ;ocvt / tty3
  2313 00005A8E [CF5A0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2314                              <1> 		 ;ocvt / tty4
  2315 00005A92 [CF5A0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2316                              <1> 		 ;ocvt / tty5
  2317 00005A96 [CF5A0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2318                              <1> 		 ;ocvt / tty6
  2319 00005A9A [CF5A0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2320                              <1> 		 ;ocvt / tty7
  2321 00005A9E [CF5A0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2322                              <1> 		 ;error / crd
  2323 00005AA2 [CF5A0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2324                              <1> 
  2325                              <1> iopen_2: ; 2: / check open write access
  2326 00005AA6 66F7D8              <1> 	neg	ax
  2327                              <1> 		;neg r1 / make inode number positive
  2328 00005AA9 B201                <1> 	mov	dl, 1 ; write access
  2329 00005AAB E8F2F8FFFF          <1> 	call	access
  2330                              <1> 		;jsr r0,access; 1 / get inode in core
  2331                              <1> 	; DL=1
  2332 00005AB0 66F705[D66C0000]00- <1> 	test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2332 00005AB8 40                  <1>
  2333                              <1>  		;bit $40000,i.flgs / is it a directory?
  2334 00005AB9 7488                <1> 	jz	short iopen_0
  2335                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2336                              <1> 	;jmp	error ; permission denied !
  2337 00005ABB E968FFFFFF          <1> 	jmp	sysmnt_err0
  2338                              <1> 	;;jnz	error		
  2339                              <1>        		; bne 2f / yes, transfer (error)
  2340                              <1>         ;;jmp     short iopen_0
  2341                              <1> 	;cmp	ax, 40
  2342                              <1> 		; cmp r1,$40. / no, is it a special file?
  2343                              <1>         ;ja	short iopen_2
  2344                              <1> 		 ;bgt 3f / no, return
  2345                              <1> 	;push	ax
  2346                              <1> 		;mov r1,-(sp) / yes
  2347                              <1> 	;movzx	ebx, al
  2348                              <1> 	;shl	bx, 1
  2349                              <1> 		; asl r1
  2350                              <1> 	;add	ebx, ipen_3 - 2
  2351                              <1> 	;jmp	dword [ebx]
  2352                              <1> 		; jmp *1f-2(r1) / figure out 
  2353                              <1> 			; / which special file it is and transfer
  2354                              <1> ;iopen_3: ; 1:
  2355                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2356                              <1>  		 ;otty / tty ; r1=2
  2357                              <1>         	 ;leadr / ppt ; r1=4
  2358                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2359                              <1> 		 ;sret / mem ; r1=6
  2360                              <1> 		 ;sret / rf0
  2361                              <1>         	 ;sret / rk0
  2362                              <1>         	 ;sret / tap0
  2363                              <1>         	 ;sret / tap1
  2364                              <1>         	 ;sret / tap2
  2365                              <1>         	 ;sret / tap3
  2366                              <1>         	 ;sret / tap4
  2367                              <1>         	 ;sret / tap5
  2368                              <1>         	 ;sret / tap6
  2369                              <1>         	 ;sret / tap7
  2370                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2371                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2372                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2373                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2374                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2375                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2376                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2377                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2378                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2379                              <1> 		 ;ocvt / tty0
  2380                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2381                              <1> 		 ;ocvt / tty1
  2382                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2383                              <1> 		 ;ocvt / tty2
  2384                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2385                              <1> 		 ;ocvt / tty3
  2386                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2387                              <1> 		 ;ocvt / tty4
  2388                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2389                              <1> 		 ;ocvt / tty5
  2390                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2391                              <1> 		 ;ocvt / tty6
  2392                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2393                              <1> 		 ;ocvt / tty7
  2394                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2395                              <1> 		 ;/ ejec / lpr
  2396                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2397                              <1> 
  2398                              <1> 
  2399                              <1> otty: ;/ open console tty for reading or writing
  2400                              <1> 	; 16/11/2015
  2401                              <1> 	; 12/11/2015
  2402                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2403                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2404                              <1> 	; 16/07/2013
  2405                              <1> 	; Retro UNIX 8086 v1 modification:
  2406                              <1> 	;  If a tty is open for read or write by
  2407                              <1> 	;     a process (u.uno), only same process can open
  2408                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2409                              <1> 	;
  2410                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2411                              <1> 	;
  2412 00005AC0 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2413 00005AC7 8A83[556D0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2414                              <1> 	; 13/01/2014
  2415 00005ACD EB02                <1> 	jmp	short ottyp
  2416                              <1> ocvt:
  2417 00005ACF 2C0A                <1> 	sub	al, 10
  2418                              <1> ottyp:
  2419                              <1> 	; 16/11/2015
  2420                              <1> 	; 12/11/2015
  2421                              <1> 	; 18/05/2015 (32 bit modifications)
  2422                              <1> 	; 06/12/2013 - 13/07/2014
  2423 00005AD1 88C6                <1> 	mov	dh, al ; tty number
  2424 00005AD3 0FB6D8              <1> 	movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2425 00005AD6 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2426                              <1> 	;26/01/2014	
  2427 00005AD8 81C3[746C0000]      <1> 	add 	ebx, ttyl
  2428 00005ADE 668B0B              <1> 	mov 	cx, [ebx]
  2429                              <1> 		   ; CL = lock value (0 or process number)
  2430                              <1> 		   ; CH = open count 
  2431 00005AE1 20C9                <1> 	and 	cl, cl
  2432                              <1> 	; 13/01/2014
  2433 00005AE3 7439                <1> 	jz 	short otty_ret
  2434                              <1> 	;
  2435                              <1> 	; 16/11/2015
  2436 00005AE5 3A0D[57700000]      <1> 	cmp 	cl, [u.uno]
  2437 00005AEB 745C                <1> 	je	short ottys_3
  2438                              <1> 	;
  2439 00005AED 0FB6D9              <1> 	movzx 	ebx, cl ; the process which has locked the tty
  2440 00005AF0 D0E3                <1> 	shl 	bl, 1
  2441 00005AF2 668B83[F46C0000]    <1> 	mov 	ax, [ebx+p.pid-2]
  2442                              <1> 	;movzx 	ebx, byte [u.uno]
  2443 00005AF9 8A1D[57700000]      <1> 	mov	bl, [u.uno]
  2444 00005AFF D0E3                <1> 	shl 	bl, 1
  2445 00005B01 663B83[146D0000]    <1> 	cmp 	ax, [ebx+p.ppid-2]
  2446 00005B08 743F                <1> 	je 	short ottys_3  ; 16/11/2015
  2447                              <1> 	;
  2448                              <1> 	; the tty is locked by another process
  2449                              <1> 	; except the parent process (p.ppid)
  2450                              <1>         ;
  2451 00005B0A C705[5D700000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2451 00005B12 0000                <1>
  2452                              <1> 			; permission denied ! error
  2453                              <1> otty_err: ; 13/01/2014
  2454 00005B14 08D2                <1> 	or 	dl, dl ; DL = 0 -> called by sysstty
  2455 00005B16 0F8569E1FFFF        <1> 	jnz	error
  2456 00005B1C F9                  <1> 	stc
  2457 00005B1D C3                  <1> 	retn
  2458                              <1> otty_ret: 
  2459                              <1> 	; 13/01/2014
  2460 00005B1E 80FE07              <1> 	cmp 	dh, 7
  2461 00005B21 761C                <1> 	jna	short ottys_2
  2462                              <1> 	; 16/11/2015
  2463                              <1> com_port_check:
  2464 00005B23 BE[926C0000]        <1> 	mov	esi, com1p
  2465 00005B28 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2466 00005B2B 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2467 00005B2D 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2468                              <1> ottys_1:
  2469                              <1> 	; 12/11/2015
  2470 00005B2E 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2471 00005B31 770C                <1> 	ja	short com_port_ready
  2472                              <1> 	;
  2473 00005B33 C705[5D700000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2473 00005B3B 0000                <1>
  2474                              <1> 			   ; device not ready ! error
  2475 00005B3D EBD5                <1> 	jmp	short otty_err	 
  2476                              <1> com_port_ready:
  2477                              <1> ottys_2:
  2478 00005B3F 08C9                <1> 	or	cl, cl  ; cl = lock/owner, ch = open count
  2479 00005B41 7506                <1> 	jnz	short ottys_3
  2480 00005B43 8A0D[57700000]      <1> 	mov	cl, [u.uno]
  2481                              <1> ottys_3:
  2482 00005B49 FEC5                <1> 	inc 	ch
  2483 00005B4B 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2484                              <1> 	; 06/12/2013
  2485 00005B4E FEC6                <1> 	inc	dh ; tty number + 1
  2486 00005B50 BB[38700000]        <1> 	mov	ebx, u.ttyp
  2487                              <1> 	; 13/01/2014
  2488 00005B55 F6C202              <1> 	test	dl, 2 ; open for read sign
  2489 00005B58 7501                <1> 	jnz	short ottys_4
  2490 00005B5A 43                  <1> 	inc	ebx
  2491                              <1> ottys_4:
  2492                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2493 00005B5B 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2494                              <1> sret:
  2495 00005B5D 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2496 00005B5F 7402                <1> 	jz	short iclose_retn
  2497 00005B61 6658                <1> 	pop 	ax
  2498                              <1> iclose_retn:	
  2499 00005B63 C3                  <1> 	retn
  2500                              <1> 
  2501                              <1> 	;
  2502                              <1> 	; Original UNIX v1 'otty' routine:
  2503                              <1> 	;	
  2504                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2505                              <1>         ;                 / reader status reg
  2506                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2507                              <1>         ;                 / punch status reg
  2508                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2509                              <1>         ;                          / console tty buffer
  2510                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2511                              <1>         ;            / console tty
  2512                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2513                              <1>         ;             / buffer header
  2514                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2515                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2516                              <1>         ;                 / tty
  2517                              <1>         ;br     sret / ?
  2518                              <1> ;sret:
  2519                              <1> 		;clr *$ps / set processor priority to zero
  2520                              <1> ;	pop	ax
  2521                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2522                              <1> ;3:
  2523                              <1> ;	retn
  2524                              <1>         	;rts r0
  2525                              <1> 	
  2526                              <1> ;ocvt:	; < open tty >
  2527                              <1> 	; 13/01/2014
  2528                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2529                              <1> 	; 24/09/2013 consistency check -> ok
  2530                              <1> 	; 16/09/2013
  2531                              <1> 	; 03/09/2013
  2532                              <1> 	; 27/08/2013
  2533                              <1> 	; 16/08/2013
  2534                              <1> 	; 16/07/2013
  2535                              <1> 	; 27/05/2013
  2536                              <1> 	; 21/05/2013
  2537                              <1> 	;
  2538                              <1> 	; Retro UNIX 8086 v1 modification !
  2539                              <1> 	; 
  2540                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2541                              <1> 	;		(exactly different than this one)
  2542                              <1> 	;	was in 'u9.s' file.
  2543                              <1> 	;
  2544                              <1> 	; 16/07/2013
  2545                              <1> 	; Retro UNIX 8086 v1 modification:
  2546                              <1> 	;  If a tty is open for read or write by
  2547                              <1> 	;     a process (u.uno), only same process can open
  2548                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2549                              <1> 	;
  2550                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2551                              <1> 
  2552                              <1> 	; 16/09/2013
  2553                              <1> 	; sub 	al, 10
  2554                              <1> 	
  2555                              <1> 	; 06/12/2013
  2556                              <1> 	;cmp	al, 7
  2557                              <1>         ;jna     short ottyp
  2558                              <1> 	; 13/01/2014
  2559                              <1> 	;jmp	short ottyp
  2560                              <1> 
  2561                              <1> 
  2562                              <1> ;oppt: / open paper tape for reading or writing
  2563                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2564                              <1> ;        tstb   pptiflg / is file already open
  2565                              <1> ;        bne    2f / yes, branch
  2566                              <1> ;1:
  2567                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2568                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2569                              <1> ;               br .+4 / for paper tape input and place in free list
  2570                              <1> ;        br     1b
  2571                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2572                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2573                              <1> ;        br     sret
  2574                              <1> ;2:
  2575                              <1> ;        jmp    error / file already open
  2576                              <1> 
  2577                              <1> iclose: 
  2578                              <1> 	; 19/05/2015
  2579                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2580                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2581                              <1> 	;
  2582                              <1> 	; close file whose i-number is in r1
  2583                              <1> 	; 
  2584                              <1> 	; INPUTS ->
  2585                              <1> 	;    r1 - inode number
  2586                              <1> 	; OUTPUTS ->
  2587                              <1> 	;    file's inode in core	
  2588                              <1> 	;    r1 - inode number (positive)
  2589                              <1> 	;
  2590                              <1> 	; ((AX = R1))
  2591                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2592                              <1> 	;        
  2593                              <1> ;/ close file whose i-number is in r1
  2594 00005B64 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2595 00005B66 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2596                              <1> 		;tst r1 / test i-number
  2597                              <1>         ;jnz	short iclose_2
  2598                              <1> 		;blt 2f / if neg., branch
  2599 00005B69 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2600                              <1> 	; 16/07/2013 
  2601 00005B6B 66F7D8              <1> 	neg	ax ; make it positive
  2602                              <1> 	; 12/01/2014
  2603 00005B6E FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2604                              <1> iclose_0:
  2605 00005B70 6683F828            <1> 	cmp	ax, 40
  2606                              <1> 		;cmp r1,$40. / is it a special file
  2607 00005B74 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2608                              <1> 		;bgt 3b / no, return
  2609                              <1> 	; 12/01/2014
  2610                              <1> 	; DL=2 -> special file was opened for reading
  2611                              <1> 	; DL=1 -> special file was opened for writing
  2612 00005B76 6650                <1> 	push	ax
  2613                              <1> 		;mov r1,-(sp) / yes, save r1 on stack
  2614 00005B78 0FB6D8              <1> 	movzx	ebx, al
  2615 00005B7B 66C1E302            <1> 	shl	bx, 2
  2616                              <1> 		; asl r1
  2617 00005B7F 81C3[835B0000]      <1> 	add	ebx, iclose_1 - 4
  2618 00005B85 FF23                <1> 	jmp	dword [ebx]
  2619                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2620                              <1> iclose_1 :
  2621 00005B87 [D35B0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2622 00005B8B [245C0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2623 00005B8F [245C0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2624 00005B93 [245C0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2625 00005B97 [245C0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2626 00005B9B [245C0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2627 00005B9F [245C0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2628 00005BA3 [245C0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2629 00005BA7 [245C0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2630                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2631                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2632 00005BAB [E25B0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2633 00005BAF [E25B0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2634 00005BB3 [E25B0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2635 00005BB7 [E25B0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2636 00005BBB [E25B0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2637 00005BBF [E25B0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2638 00005BC3 [E25B0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2639 00005BC7 [E25B0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2640 00005BCB [E25B0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2641 00005BCF [E25B0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2642                              <1> 
  2643                              <1> 	; 1:
  2644                              <1> 	;        ctty   / tty
  2645                              <1> 	;        cppt   / ppt
  2646                              <1> 	;        sret   / mem
  2647                              <1> 	;        sret   / rf0
  2648                              <1> 	;        sret   / rk0
  2649                              <1> 	;        sret   / tap0
  2650                              <1> 	;        sret   / tap1
  2651                              <1> 	;        sret   / tap2
  2652                              <1> 	;        sret   / tap3
  2653                              <1> 	;        sret   / tap4
  2654                              <1> 	;        sret   / tap5
  2655                              <1> 	;        sret   / tap6
  2656                              <1> 	;        sret   / tap7
  2657                              <1> 	;        ccvt   / tty0
  2658                              <1> 	;        ccvt   / tty1
  2659                              <1> 	;        ccvt   / tty2
  2660                              <1> 	;        ccvt   / tty3
  2661                              <1> 	;        ccvt   / tty4
  2662                              <1> 	;        ccvt   / tty5
  2663                              <1> 	;        ccvt   / tty6
  2664                              <1> 	;        ccvt   / tty7
  2665                              <1> 	;        error / crd
  2666                              <1> 
  2667                              <1> ;iclose_2: ; 2: / negative i-number
  2668                              <1> 	;neg	ax
  2669                              <1> 		;neg r1 / make it positive
  2670                              <1> 	;cmp	ax, 40
  2671                              <1> 		;cmp r1,$40. / is it a special file?
  2672                              <1>         ;ja	short @b
  2673                              <1> 		;bgt    3b / no. return
  2674                              <1> 	;push	ax
  2675                              <1> 		;mov r1,-(sp)
  2676                              <1> 	;movzx	ebx, al
  2677                              <1> 	;shl	bx, 1
  2678                              <1> 		;asl r1 / yes. compute jump address and transfer
  2679                              <1> 	;add	ebx, iclose_3 - 2
  2680                              <1> 	;jmp	dword [ebx]
  2681                              <1> 		;jmp *1f-2(r1) / figure out 
  2682                              <1> ;iclose_3:
  2683                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2684                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2685                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2686                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2687                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2688                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2689                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2690                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2691                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2692                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2693                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2694                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2695                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2696                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2697                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2698                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2699                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2700                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2701                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2702                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2703                              <1> 	
  2704                              <1> 	;1:
  2705                              <1> 	;      	ctty   / tty
  2706                              <1> 	;       leadr  / ppt
  2707                              <1> 	;       sret   / mem
  2708                              <1> 	;       sret   / rf0
  2709                              <1> 	;       sret   / rk0
  2710                              <1> 	;       sret   / tap0
  2711                              <1> 	;       sret   / tap1
  2712                              <1> 	;       sret   / tap2
  2713                              <1> 	;       sret   / tap3
  2714                              <1> 	;       sret   / tap4
  2715                              <1> 	;       sret   / tap5
  2716                              <1> 	;       sret   / tap6
  2717                              <1> 	;       sret   / tap7
  2718                              <1> 	;       ccvt   / tty0
  2719                              <1> 	;       ccvt   / tty1
  2720                              <1> 	;       ccvt   / tty2
  2721                              <1> 	;       ccvt   / tty3
  2722                              <1> 	;       ccvt   / tty4
  2723                              <1> 	;       ccvt   / tty5
  2724                              <1> 	;       ccvt   / tty6
  2725                              <1> 	;       ccvt   / tty7
  2726                              <1> 	;/       ejec / lpr
  2727                              <1> 
  2728                              <1> ctty: ; / close console tty
  2729                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2730                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2731                              <1> 	;
  2732                              <1> 	; Retro UNIX 8086 v1 modification !
  2733                              <1> 	; (DL = 2 -> it is open for reading)
  2734                              <1> 	; (DL = 1 -> it is open for writing)
  2735                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  2736                              <1> 	;
  2737                              <1> 	; 06/12/2013
  2738 00005BD3 0FB61D[57700000]    <1>         movzx   ebx, byte [u.uno] ; process number
  2739 00005BDA 8A83[556D0000]      <1>         mov     al, [ebx+p.ttyc-1]
  2740                              <1> 	; 13/01/2014
  2741 00005BE0 EB02                <1> 	jmp	short cttyp
  2742                              <1> ccvt:
  2743 00005BE2 2C0A                <1> 	sub 	al, 10
  2744                              <1> cttyp:	
  2745                              <1> 	; 18/05/2015 (32 bit modifications)
  2746                              <1> 	; 16/08/2013 - 26/01/2014
  2747 00005BE4 0FB6D8              <1> 	movzx 	ebx, al ; tty number (0 to 9)
  2748 00005BE7 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  2749                              <1> 	; 26/01/2014
  2750 00005BE9 81C3[746C0000]      <1> 	add 	ebx, ttyl
  2751 00005BEF 88C6                <1> 	mov 	dh, al ; tty number
  2752 00005BF1 668B03              <1> 	mov 	ax, [ebx]
  2753                              <1> 		   ; AL = lock value (0 or process number)
  2754                              <1> 		   ; AH = open count 
  2755 00005BF4 20E4                <1> 	and 	ah, ah
  2756 00005BF6 750F                <1> 	jnz	short ctty_ret
  2757 00005BF8 C705[5D700000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  2757 00005C00 0000                <1>
  2758                              <1> 			; device not open ! error
  2759                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  2760 00005C02 E97EE0FFFF          <1> 	jmp	error
  2761                              <1> 	; 26/01/2014
  2762                              <1> ctty_ret:
  2763 00005C07 FECC                <1> 	dec 	ah ; decrease open count
  2764 00005C09 7502                <1> 	jnz	short ctty_1
  2765 00005C0B 30C0                <1> 	xor	al, al ; unlock/free tty
  2766                              <1> ctty_1:
  2767 00005C0D 668903              <1> 	mov 	[ebx], ax ; close tty instance
  2768                              <1> 	;
  2769 00005C10 BB[38700000]        <1> 	mov	ebx, u.ttyp
  2770 00005C15 F6C201              <1> 	test	dl, 1 ; open for write sign
  2771 00005C18 7401                <1> 	jz	short ctty_2
  2772 00005C1A 43                  <1> 	inc	ebx
  2773                              <1> ctty_2:
  2774 00005C1B FEC6                <1> 	inc	dh ; tty number + 1
  2775 00005C1D 3A33                <1> 	cmp	dh, [ebx]
  2776 00005C1F 7503                <1> 	jne	short cret
  2777                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  2778 00005C21 C60300              <1> 	mov	byte [ebx], 0
  2779                              <1> cret:
  2780 00005C24 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2781 00005C26 7402                <1> 	jz	short ctty_3
  2782 00005C28 6658                <1> 	pop	ax
  2783                              <1> ctty_3:
  2784 00005C2A C3                  <1> 	retn
  2785                              <1> 
  2786                              <1> ;ctty_err: ; 13/01/2014
  2787                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  2788                              <1> ;	jnz	error
  2789                              <1> ;	stc
  2790                              <1> ;	retn
  2791                              <1> 
  2792                              <1> 
  2793                              <1> 	; Original UNIX v1 'ctty' routine:
  2794                              <1> 	;	
  2795                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  2796                              <1> 	;		;/ point r5 to the console tty buffer
  2797                              <1>         ;decb   (r5) / dec number of processes using console tty
  2798                              <1>         ;br     sret / return via sret
  2799                              <1> 
  2800                              <1> ;ccvt:	; < close tty >
  2801                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2802                              <1> 	;
  2803                              <1> 	; Retro UNIX 8086 v1 modification !
  2804                              <1> 	; 
  2805                              <1> 	; In original UNIX v1, 'ccvt' routine 
  2806                              <1> 	;		(exactly different than this one)
  2807                              <1> 	;	was in 'u9.s' file.
  2808                              <1> 	;
  2809                              <1> 	; DL = 2 -> it is open for reading
  2810                              <1> 	; DL = 1 -> it is open for writing
  2811                              <1> 	;
  2812                              <1> 	; 17/09/2013
  2813                              <1> 	;sub 	al, 10
  2814                              <1> 	;cmp	al, 7
  2815                              <1> 	;jna	short cttyp
  2816                              <1> 	; 13/01/2014
  2817                              <1> 	;jmp	short cttyp
  2818                              <1> 
  2819                              <1> ;cppt: / close paper tape
  2820                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  2821                              <1> ;1:
  2822                              <1> ;        mov    $240,*$ps /set process or priority to 5
  2823                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  2824                              <1> ;                          / and assign to free list
  2825                              <1> ;               br sret
  2826                              <1> ;        br     1b
  2827                              <1> 
  2828                              <1> ;ejec:	
  2829                              <1> ;	jmp	error
  2830                              <1> ;/ejec:
  2831                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  2832                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  2833                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  2834                              <1> ;/       br     sret / return to caller via 'sret'
  2000                                  %include 'u8.s'        ; 11/06/2015
  2001                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS8.INC
  2002                              <1> ; Last Modification: 24/12/2021
  2003                              <1> ; ----------------------------------------------------------------------------
  2004                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2005                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2006                              <1> ;
  2007                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2008                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2009                              <1> ; <Bell Laboratories (17/3/1972)>
  2010                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2011                              <1> ;
  2012                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2013                              <1> ;
  2014                              <1> ; ****************************************************************************
  2015                              <1> 
  2016                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2017                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2018                              <1> ;; Word 1, byte 0 = device id
  2019                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2020                              <1> ;;          bit 9 = write bit
  2021                              <1> ;;	    bit 10 = read bit	  
  2022                              <1> ;;	    bit 12 = waiting to write bit	
  2023                              <1> ;;	    bit 13 = waiting to read bit
  2024                              <1> ;;	    bit 15 = inhibit bit
  2025                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2026                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2027                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2028                              <1> ;;
  2029                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2030                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2031                              <1> ;;
  2032                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2033                              <1> ;; Word 1, Byte 0 = device id
  2034                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2035                              <1> ;;          bit 9 = write bit
  2036                              <1> ;;	    bit 10 = read bit	  
  2037                              <1> ;;	    bit 12 = waiting to write bit	
  2038                              <1> ;;	    bit 13 = waiting to read bit
  2039                              <1> ;;	    bit 15 = inhibit bit
  2040                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2041                              <1> ;;
  2042                              <1> ;; Original UNIX v1 ->
  2043                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2044                              <1> ;; Original UNIX v1 -> 
  2045                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2046                              <1> ;;
  2047                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2048                              <1> ;;
  2049                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2050                              <1> ;;          0 = fd0
  2051                              <1> ;;	    1 = fd1
  2052                              <1> ;;	    2 = hd0
  2053                              <1> ;;	    3 = hd1
  2054                              <1> ;;	    4 = hd2
  2055                              <1> ;;	    5 = hd3
  2056                              <1> 
  2057                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2058                              <1> 
  2059                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2060                              <1> 	; 26/04/2013
  2061                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2062                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2063                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2064                              <1> 
  2065                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2066                              <1> 	; 26/04/2013
  2067                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2068                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2069                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2070                              <1> 
  2071                              <1> bread: 
  2072                              <1> 	; 14/07/2015
  2073                              <1> 	; 10/07/2015
  2074                              <1> 	; 09/06/2015
  2075                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2076                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2077                              <1> 	;	
  2078                              <1> 	; / read a block from a block structured device
  2079                              <1> 	;
  2080                              <1> 	; INPUTS ->
  2081                              <1> 	;    [u.fopf] points to the block number
  2082                              <1> 	;    CX = maximum block number allowed on device
  2083                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2084                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2085                              <1> 	;    [u.count]	number of bytes to read in
  2086                              <1> 	; OUTPUTS ->
  2087                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2088                              <1> 	;    [u.fopf] points to next consecutive block to be read
  2089                              <1> 	;
  2090                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2091                              <1> 	;
  2092                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2093                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2094                              <1> 	;	is increased by 1. For example: If user/program request 
  2095                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2096                              <1> 	;  	the next block number just as 512 byte reading is done.
  2097                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2098                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2099                              <1> 	;       enough to keep byte position/offset of the disk), this
  2100                              <1> 	;	defect will not be corrected, user/program must request
  2101                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2102                              <1> 	;       for achieving correct result. In future version(s), 
  2103                              <1> 	;	this defect will be corrected by using different 
  2104                              <1> 	;       user (u) structure.  26/07/2013 - Erdogan Tan 	
  2105                              <1> 
  2106                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2107                              <1> 			       ; / (only works on tape)
  2108                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2109                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2110                              <1> ;1:
  2111                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2112                              <1> 			    ; / maximum block # allowed on device
  2113                              <1> 		; jnb short @f
  2114                              <1> 		; bhis	1f / yes, 1f (error)
  2115                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2116                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2117                              <1> 		; mov (sp)+,r1 / return block # to r1
  2118                              <1> 		; inc r1 / bump block # to next consecutive block
  2119                              <1> 		; dec (sp) / "2-1-cold" on stack
  2120                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2121                              <1> ;1:
  2122                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2123                              <1> 	;push	ecx ; **
  2124                              <1> 	;26/04/2013
  2125                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2126 00005C2B 2C03                <1> 	sub	al, 3
  2127                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2128 00005C2D A2[70700000]        <1> 	mov	[u.brwdev], al
  2129                              <1> 	; 09/06/2015
  2130 00005C32 0FB6D8              <1> 	movzx	ebx, al
  2131 00005C35 8B8B[0E670000]      <1> 	mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2132                              <1> bread_0:
  2133 00005C3B 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2134                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2135                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2136 00005C3C 8B1D[18700000]      <1> 	mov	ebx, [u.fofp]
  2137 00005C42 8B03                <1> 	mov	eax, [ebx]
  2138 00005C44 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2139                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2140                              <1> 			       ; / block #
  2141 00005C47 39C8                <1> 	cmp	eax, ecx
  2142                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2143                              <1>        	                     ; / block number allowed
  2144                              <1> 	;jnb	error 	     ; 18/04/2013
  2145                              <1> 		; bhis error10 / yes, error
  2146 00005C49 720F                <1> 	jb	short bread_1
  2147 00005C4B C705[5D700000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error	
  2147 00005C53 0000                <1>
  2148 00005C55 E92BE0FFFF          <1> 	jmp	error
  2149                              <1> bread_1:
  2150                              <1> 	; inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2151                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2152                              <1> 	; eAX = Block number (zero based)
  2153                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2154                              <1> preread: ;; call preread
  2155 00005C5A BF[70700000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2156 00005C5F E862020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2157                              <1> 	;; jc 	error
  2158                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2159                              <1>         ; eAX = Block/Sector number (r1)
  2160                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2161                              <1> 	; 14/03/2013
  2162 00005C64 740A                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2163                              <1>        		; br 1f / branch if block already in a I/O buffer
  2164 00005C66 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2165                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2166 00005C6B E8B3010000          <1> 	call	poke
  2167                              <1>         	; jsr r0,poke / perform the read
  2168                              <1> 	;;jc	error ;2 0/07/2013
  2169                              <1> ; 1:
  2170                              <1>  		; clr *$ps / ps = 0
  2171                              <1>         	; rts r0
  2172                              <1> ;; return from preread
  2173                              <1> bread_2:
  2174 00005C70 66810B0040          <1> 	or	word [ebx], 4000h 
  2175                              <1> 		; bis $40000,(r5) 
  2176                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2177                              <1> bread_3: ; 1:
  2178 00005C75 66F7030024          <1> 	test	word [ebx], 2400h
  2179                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2180 00005C7A 7407                <1> 	jz	short bread_4
  2181                              <1> 		; beq 1f / no
  2182                              <1> 		; cmp cdev,$1 / disk or drum?
  2183                              <1> 		; ble 2f / yes
  2184                              <1> 		; tstb uquant / is the time quantum = 0?
  2185                              <1> 		; bne 2f / no, 2f
  2186                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2187                              <1> 		; jsr r0,sleep; 31. 
  2188                              <1> 			; / put process to sleep in channel 31 (tape)
  2189                              <1> 		; mov (sp)+,r5 / restore r5
  2190                              <1> 		; br 1b / go back
  2191                              <1> ; 2: / drum or disk
  2192                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2193 00005C7C E8CCF3FFFF          <1> 	call	idle
  2194                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2195 00005C81 EBF2                <1> 	jmp	short bread_3
  2196                              <1>        		; br 1b
  2197                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2198 00005C83 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2199                              <1> 		; bic $40000,(r5) / clear bit 14
  2200                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2201 00005C88 83C308              <1> 	add	ebx, 8
  2202                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2203                              <1> 	; 09/06/2015
  2204 00005C8B 66833D[6D700000]00  <1> 	cmp	word [u.pcount], 0
  2205 00005C93 7705                <1> 	ja	short bread_5
  2206 00005C95 E8A0F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2207                              <1> bread_5:
  2208                              <1> 	; eBX = system (I/O) buffer address
  2209 00005C9A E870000000          <1> 	call	dioreg
  2210                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2211                              <1> 	; esi =  start address of the transfer (in the buffer)
  2212                              <1> 	; edi =  [u.pbase], destination address in user's memory space
  2213                              <1> 	; ecx =  transfer count (in bytes)
  2214                              <1> 	;
  2215                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2216                              <1> ;   / of users data
  2217 00005C9F F3A4                <1> 	rep	movsb
  2218                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2219                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2220                              <1>        		; bne 1b
  2221 00005CA1 59                  <1> 	pop	ecx ; **
  2222 00005CA2 833D[2C700000]00    <1> 	cmp	dword [u.count], 0
  2223                              <1> 		; tst u.count / done
  2224 00005CA9 7790                <1> 	ja	short bread_0 ; 09/06/2015
  2225                              <1>        		; beq 1f / yes, return
  2226                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2227                              <1>        		; br bread / read some more
  2228                              <1> ; 1:
  2229 00005CAB 58                  <1> 	pop	eax ; ****
  2230                              <1>        		; mov (sp)+,r0
  2231 00005CAC C3                  <1>         retn		; 09/06/2015
  2232                              <1> 	;jmp     ret_ 
  2233                              <1> 		;jmp ret  / jump to routine that called readi
  2234                              <1> 
  2235                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2236                              <1> 	; 26/04/2013
  2237                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2238                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2239                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2240                              <1> 				
  2241                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2242                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2243                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2244                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2245                              <1> 
  2246                              <1> bwrite: 
  2247                              <1> 	; 14/07/2015
  2248                              <1> 	; 10/07/2015
  2249                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2250                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2251                              <1> 	;	
  2252                              <1> 	;; / write on block structured device
  2253                              <1> 	;
  2254                              <1> 	; INPUTS ->
  2255                              <1> 	;    [u.fopf] points to the block number
  2256                              <1> 	;    CX = maximum block number allowed on device
  2257                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2258                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2259                              <1> 	;    [u.count]	number of bytes to user desires to write
  2260                              <1> 	; OUTPUTS ->
  2261                              <1> 	;    [u.fopf] points to next consecutive block to be written into
  2262                              <1> 	;
  2263                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2264                              <1> 	;
  2265                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2266                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2267                              <1> 	;	is increased by 1. For example: If user/program request 
  2268                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2269                              <1> 	;  	the next block number just as 512 byte writing is done.
  2270                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2271                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2272                              <1> 	;       enough to keep byte position/offset of the disk), this
  2273                              <1> 	;	defect will not be corrected, user/program must request
  2274                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2275                              <1> 	;       for achieving correct result. In future version(s), 
  2276                              <1> 	;	this defect will be corrected by using different 
  2277                              <1> 	;       user (u) structure.  26/07/2013 - Erdogan Tan 	
  2278                              <1> 
  2279                              <1>        		; jsr r0,tstdeve / test the device for an error
  2280                              <1> 	;push	ecx ; **
  2281                              <1> 	;26/04/2013
  2282                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2283 00005CAD 2C03                <1> 	sub	al, 3
  2284                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2285 00005CAF A2[70700000]        <1> 	mov	[u.brwdev], al
  2286                              <1> 	; 09/06/2015
  2287 00005CB4 0FB6D8              <1> 	movzx	ebx, al
  2288 00005CB7 8B8B[0E670000]      <1> 	mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2289                              <1> bwrite_0:
  2290 00005CBD 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2291                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2292                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2293 00005CBE 8B1D[18700000]      <1> 	mov	ebx, [u.fofp]
  2294 00005CC4 8B03                <1> 	mov	eax, [ebx]       
  2295 00005CC6 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2296                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2297 00005CC9 39C8                <1> 	cmp	eax, ecx
  2298                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2299                              <1>        	                     ; / block number allowed
  2300                              <1> 	;jnb	error	     ; 18/04/2013
  2301                              <1> 		; bhis error10 / yes, error
  2302 00005CCB 720F                <1>      	jb	short bwrite_1
  2303 00005CCD C705[5D700000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error	
  2303 00005CD5 0000                <1>
  2304 00005CD7 E9A9DFFFFF          <1> 	jmp	error
  2305                              <1> bwrite_1:
  2306                              <1> 	; inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2307                              <1> 		; inc *u.fofp / no, increment block number
  2308                              <1> 	; 09/06/2015 - 10/07/2015
  2309 00005CDC 66833D[6D700000]00  <1> 	cmp	word [u.pcount], 0
  2310 00005CE4 7705                <1> 	ja	short bwrite_2
  2311 00005CE6 E84BF9FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2312                              <1> bwrite_2:
  2313 00005CEB BF[70700000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2314 00005CF0 E8C4000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2315                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2316                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2317 00005CF5 E815000000          <1>         call	dioreg
  2318                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2319                              <1> 	; esi =  destination address (in the buffer)
  2320                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2321                              <1> 	; ecx =  transfer count (in bytes)
  2322                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2323 00005CFA 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2324 00005CFC F3A4                <1> 	rep	movsb
  2325                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2326                              <1>        		; dec r3 / area to the I/O buffer
  2327                              <1>        		; bne 1b
  2328 00005CFE E8FE000000          <1> 	call	dskwr
  2329                              <1> 		; jsr r0,dskwr / write it out on the device
  2330 00005D03 59                  <1> 	pop	ecx ; **
  2331 00005D04 833D[2C700000]00    <1>         cmp     dword [u.count], 0
  2332                              <1> 		; tst u.count / done
  2333 00005D0B 77B0                <1> 	ja	short bwrite_0 ; 09/06/2015
  2334                              <1> 		; beq 1f / yes, 1f
  2335                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2336                              <1>        		; br bwrite / go back and write next block
  2337                              <1> ; 1:
  2338 00005D0D 58                  <1> 	pop	eax ; ****
  2339                              <1>        		; mov (sp)+,r0
  2340 00005D0E C3                  <1> 	retn		; 09/06/2015
  2341                              <1>         ;jmp     ret_ 
  2342                              <1> 		; jmp ret / return to routine that called writei
  2343                              <1> ;error10:
  2344                              <1> ;       jmp     error  ; / see 'error' routine
  2345                              <1> 
  2346                              <1> dioreg:
  2347                              <1> 	; 14/07/2015
  2348                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2349                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2350                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2351                              <1> 	;	
  2352                              <1> 	; bookkeeping on block transfers of data
  2353                              <1> 	;
  2354                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2355                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2356                              <1> 	; 10/07/2015
  2357                              <1> 	; * returns byte offset from beginning of current sector buffer
  2358                              <1> 	; (beginning of data) in ESI
  2359                              <1> 	;
  2360 00005D0F 8B0D[2C700000]      <1> 	mov	ecx, [u.count]
  2361                              <1> 		; mov u.count,r3 / move char count to r3
  2362 00005D15 81F900020000        <1>        	cmp 	ecx, 512
  2363                              <1> 		; cmp r3,$512. / more than 512. char?
  2364 00005D1B 7605                <1> 	jna	short dioreg_0
  2365                              <1> 		; blos 1f / no, branch
  2366 00005D1D B900020000          <1> 	mov	ecx, 512
  2367                              <1> 		; mov $512.,r3 / yes, just take 512.
  2368                              <1> dioreg_0:
  2369                              <1> 	; 09/06/2015
  2370 00005D22 663B0D[6D700000]    <1> 	cmp	cx, [u.pcount]
  2371 00005D29 7607                <1> 	jna	short dioreg_1
  2372 00005D2B 668B0D[6D700000]    <1> 	mov	cx, [u.pcount]
  2373                              <1> dioreg_1:
  2374                              <1> ; 1:
  2375 00005D32 8B15[28700000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2376                              <1> 	        ; mov u.base,r2 / put users base in r2
  2377 00005D38 010D[30700000]      <1> 	add	[u.nread], ecx
  2378                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2379 00005D3E 290D[2C700000]      <1> 	sub	[u.count], ecx
  2380                              <1> 		; sub r3,u.count / update count
  2381 00005D44 010D[28700000]      <1> 	add	[u.base], ecx
  2382                              <1> 		; add r3,u.base / update base
  2383                              <1> 	; 10/07/2015
  2384                              <1> 	; Retro UNIX 386 v1 - modification !
  2385                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2386                              <1> 	; (It will point to next byte position instead of next block no.)
  2387 00005D4A 8B35[18700000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2388 00005D50 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2389 00005D52 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2390 00005D54 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2391 00005D59 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2392 00005D5B 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2393                              <1> 	; 09/06/2015 - 10/07/2015
  2394 00005D5D 66290D[6D700000]    <1> 	sub	[u.pcount], cx
  2395 00005D64 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2396 00005D6A 8B3D[69700000]      <1> 	mov	edi, [u.pbase]
  2397 00005D70 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2398 00005D76 01D7                <1> 	add	edi, edx
  2399 00005D78 893D[69700000]      <1> 	mov	[u.pbase], edi
  2400 00005D7E 010D[69700000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2401 00005D84 C3                  <1> 	retn
  2402                              <1> 		; rts r0 / return
  2403                              <1> 
  2404                              <1> dskrd:
  2405                              <1> 	; 18/08/2015
  2406                              <1> 	; 02/07/2015
  2407                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2408                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2409                              <1> 	;
  2410                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2411                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2412                              <1> 	; (number specified in r1) in the acquired buffer.)
  2413                              <1> 	; If the device is busy at the time dskrd is called,	
  2414                              <1> 	; dskrd calls idle.
  2415                              <1> 	; 
  2416                              <1> 	; INPUTS ->
  2417                              <1> 	;    r1 - block number
  2418                              <1> 	;    cdev - current device number 
  2419                              <1> 	; OUTPUTS ->
  2420                              <1> 	;    r5 - points to first data word in I/O buffer
  2421                              <1> 	;
  2422                              <1> 	; ((AX = R1)) input/output
  2423                              <1> 	; ((BX = R5)) output 
  2424                              <1> 	;
  2425                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2426                              <1> 	;
  2427 00005D85 E82E010000          <1> 	call 	bufaloc
  2428                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2429                              <1> 			       ; / get a free I/O buffer
  2430                              <1> 	;;jc	error ; 20/07/2013
  2431 00005D8A 741B                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2432                              <1>        		; br 1f / branch if block already in a I/O buffer
  2433                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2434 00005D8C 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2435                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2436                              <1> 		               ; / I/O queue entry for buffer
  2437 00005D91 E88D000000          <1> 	call	poke
  2438                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2439                              <1> 			    ; /	bit 10=1 says read
  2440                              <1> 	; 09/06/2015
  2441 00005D96 730F                <1> 	jnc	short dskrd_1
  2442                              <1> 	;
  2443 00005D98 C705[5D700000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2443 00005DA0 0000                <1>
  2444 00005DA2 E9DEDEFFFF          <1> 	jmp	error
  2445                              <1> dskrd_1: ; 1:
  2446                              <1>        		;clr *$ps
  2447 00005DA7 66F7030024          <1>        	test	word [ebx], 2400h
  2448                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2449                              <1> 				; / jump to idle
  2450 00005DAC 7407                <1>        	jz	short dskrd_2
  2451                              <1> 		; beq 1f
  2452                              <1>         ;;mov   ecx, [s.wait_]
  2453 00005DAE E89AF2FFFF          <1>        	call	idle
  2454                              <1> 		; jsr r0,idle; s.wait+2
  2455 00005DB3 EBF2                <1> 	jmp 	short dskrd_1
  2456                              <1>        		; br 1b
  2457                              <1> dskrd_2: ; 1:
  2458 00005DB5 83C308              <1>         add	ebx, 8
  2459                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2460                              <1> 			  ; / just read in
  2461 00005DB8 C3                  <1>        	retn
  2462                              <1> 		; rts r0
  2463                              <1> 
  2464                              <1> bwslot:
  2465                              <1> 	; 10/07/2015
  2466                              <1> 	;	If the block/sector is not placed in a buffer
  2467                              <1> 	;	before 'wslot', it must be read before
  2468                              <1> 	;	it is written! (Otherwise transfer counts less
  2469                              <1> 	;	than 512 bytes will be able to destroy existing 
  2470                              <1> 	;	data on disk.)
  2471                              <1> 	;
  2472                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2473                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2474                              <1> 	; Retro UNIX 8086 v1 modification !
  2475                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2476                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2477                              <1> 	;	-> eAX = block number
  2478                              <1> 	;
  2479 00005DB9 E808010000          <1> 	call	bufaloc_0
  2480 00005DBE 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2481                              <1> bwslot_0:
  2482                              <1> 	; 10/07/2015
  2483 00005DC0 8B35[18700000]      <1> 	mov	esi, [u.fofp]
  2484 00005DC6 8B06                <1> 	mov	eax, [esi]
  2485 00005DC8 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2486 00005DCD 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2487                              <1> 		       ; recent disk data must be placed in the buffer
  2488 00005DCF 813D[2C700000]0002- <1> 	cmp	dword [u.count], 512
  2488 00005DD7 0000                <1>
  2489 00005DD9 730F                <1> 	jnb	short wslot_0	
  2490                              <1> bwslot_1:
  2491 00005DDB E8ACFFFFFF          <1> 	call	dskrd_0
  2492 00005DE0 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again	
  2493 00005DE3 EB05                <1> 	jmp 	short wslot_0
  2494                              <1> 
  2495                              <1> wslot:
  2496                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2497                              <1> 	; 		(32 bit modifications)
  2498                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2499                              <1> 	;
  2500                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2501                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2502                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2503                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2504                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2505                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2506                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2507                              <1> 	;
  2508                              <1> 	; INPUTS ->
  2509                              <1>  	;    r1 - block number
  2510                              <1> 	;    cdev - current (block/disk) device number
  2511                              <1>  	;
  2512                              <1> 	; OUTPUTS ->
  2513                              <1> 	;    bufp - bits 9 and 15 are set, 
  2514                              <1> 	;           the remainder of the word left unchanged
  2515                              <1> 	;    r5 - points to first data word in I/O buffer
  2516                              <1> 	;
  2517                              <1> 	; ((AX = R1)) input/output
  2518                              <1> 	; ((BX = R5)) output 
  2519                              <1> 	;
  2520                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2521                              <1> 
  2522 00005DE5 E8CE000000          <1> 	call	bufaloc
  2523                              <1> 	; 10/07/2015
  2524                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2525                              <1>         	; br 1f / word in buffer in r5
  2526                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2527                              <1>         ; eAX = Block/Sector number (r1)
  2528                              <1> wslot_0: ;1:
  2529 00005DEA 66F7030024          <1>      	test	word [ebx], 2400h
  2530                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2531                              <1> 				; / of I/O queue entry
  2532 00005DEF 7407                <1> 	jz	short wslot_1
  2533                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2534                              <1> 		     ; / or not waiting to read)
  2535                              <1> 
  2536                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2537 00005DF1 E857F2FFFF          <1> 	call	idle
  2538                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2539                              <1>        	                     ; / idle
  2540 00005DF6 EBF2                <1> 	jmp	short wslot_0
  2541                              <1> 		; br 1b / till finished
  2542                              <1> wslot_1: ;1:
  2543 00005DF8 66810B0082          <1>         or      word [ebx], 8200h
  2544                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2545                              <1>                             	 ; / (write, inhibit bits)
  2546                              <1>        		; clr     *$ps / clear processor status
  2547 00005DFD 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2548                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2549                              <1> 			  ; / for this block
  2550 00005E00 C3                  <1>        	retn
  2551                              <1> 		; rts r0
  2552                              <1> dskwr:
  2553                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2554                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2555                              <1> 	;
  2556                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2557                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2558                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2559                              <1> 	; previously has supplied all the information required in the
  2560                              <1> 	; I/O queue entry.
  2561                              <1> 	;
  2562                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2563                              <1> 	;
  2564                              <1> 	;
  2565 00005E01 8B1D[CA6F0000]      <1> 	mov	ebx, [bufp]
  2566 00005E07 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2567                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2568                              <1>                                   ; / bottom of queue
  2569 00005E0C E812000000          <1> 	call	poke
  2570                              <1> 	; 09/06/2015
  2571 00005E11 730F                <1> 	jnc	short dskwr_1
  2572 00005E13 C705[5D700000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2572 00005E1B 0000                <1>
  2573 00005E1D E963DEFFFF          <1> 	jmp	error
  2574                              <1> dskwr_1:
  2575 00005E22 C3                  <1> 	retn
  2576                              <1> 
  2577                              <1> 
  2578                              <1> ;ppoke:
  2579                              <1>        		; mov $340,*$ps
  2580                              <1>        		; jsr r0,poke
  2581                              <1>        		; clr *$ps
  2582                              <1> 		; rts r0
  2583                              <1> poke:
  2584                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2585                              <1> 	; 24/10/2015
  2586                              <1> 	; 20/08/2015
  2587                              <1> 	; 18/08/2015
  2588                              <1> 	; 02/07/2015
  2589                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2590                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2591                              <1> 	;
  2592                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2593                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2594                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2595                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2596                              <1> 	;
  2597                              <1> 	; Basic I/O functions for all block structured devices
  2598                              <1> 	;
  2599                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2600                              <1> 	;
  2601                              <1> 	; 20/07/2013 modifications
  2602                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2603                              <1> 	; INPUTS -> 
  2604                              <1> 	;        (EBX = buffer header address)
  2605                              <1> 	; OUTPUTS ->
  2606                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2607                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2608                              <1> 	;		(drive not ready or r/w error!)
  2609                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2610                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2611                              <1> 	;        (also it indicates invalid buffer data)
  2612                              <1> 	;
  2613 00005E23 53                  <1> 	push	ebx
  2614                              <1>        		; mov r1,-(sp)
  2615                              <1>        		; mov r2,-(sp)
  2616                              <1>        		; mov r3,-(sp)
  2617 00005E24 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2618                              <1> 	;
  2619                              <1> 	; 09/06/2015
  2620                              <1> 	; (permit read/write after a disk  R/W error)
  2621 00005E25 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2622 00005E27 B001                <1> 	mov	al, 1
  2623 00005E29 D2E0                <1> 	shl	al, cl
  2624 00005E2B 8405[F26F0000]      <1> 	test 	al, [active] ; busy ? (error)
  2625 00005E31 7408                <1> 	jz	short poke_0
  2626 00005E33 F6D0                <1> 	not	al
  2627 00005E35 2005[F26F0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2628                              <1> poke_0:
  2629 00005E3B BE[EA6F0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2630                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2631                              <1> 					 ; / I/O queue pointer
  2632                              <1> poke_1: ; 1:
  2633 00005E40 83EE04              <1>         sub	esi, 4
  2634 00005E43 8B1E                <1> 	mov	ebx, [esi]
  2635                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2636 00005E45 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2637 00005E48 F6C406              <1>        	test	ah, 06h
  2638                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2639                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2640                              <1> 			       ; / queue entry
  2641 00005E4B 745C                <1>         jz      short poke_5
  2642                              <1> 		; beq 2f / branch to 2f if both are clear
  2643                              <1> 	; 31/07/2013
  2644                              <1> 	;test	ah, 0B0h ; (*)
  2645                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2646                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2647                              <1>         ;jnz     short poke_5 ; 31/07/2013 (*)
  2648                              <1> 		; bne 2f / branch if any are set
  2649                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2650                              <1>     		; movb (r1),r3 / get device id
  2651 00005E4D 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2652                              <1> 	;mov	edi, ecx ; 26/04/2013
  2653 00005E50 31C0                <1> 	xor 	eax, eax ; 0
  2654                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2655                              <1> 		; tstb deverr(r3) / test for errors on this device
  2656                              <1>        	;jna	short poke_2 
  2657                              <1> 		; beq 3f / branch if no errors
  2658                              <1> 	; 02/07/2015
  2659                              <1> 	;dec	eax
  2660                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2661                              <1>        		; mov $-1,2(r1) / destroy associativity
  2662                              <1> 	;shr	eax, 24
  2663                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2664                              <1> 		; clrb 1(r1) / do not do I/O
  2665                              <1> 	;jmp     short poke_5
  2666                              <1>         ;       ; br 2f
  2667                              <1>                 ; rts r0
  2668                              <1> poke_2: ; 3:
  2669                              <1> 	; 02/07/2015
  2670 00005E52 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2671 00005E54 7453                <1> 	jz	short poke_5
  2672 00005E56 FEC0                <1> 	inc	al ; mov ax, 1
  2673 00005E58 FEC9                <1> 	dec	cl
  2674 00005E5A 7402                <1> 	jz	short poke_3
  2675                              <1> 	; 26/04/2013 Modification
  2676                              <1> 	;inc	al ; mov ax, 1
  2677                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2678                              <1> 	;jz	short poke_3 ; cl = 0
  2679 00005E5C D2E0                <1> 	shl	al, cl ; shl ax, cl
  2680                              <1> poke_3:
  2681                              <1> 	;test	[active], ax
  2682 00005E5E 8405[F26F0000]      <1> 	test	[active], al
  2683                              <1> 		; bit $2,active / test disk busy bit
  2684 00005E64 7543                <1> 	jnz     short poke_5
  2685                              <1> 		; bne 2f / branch if bit is set
  2686                              <1> 	;or	[active], ax
  2687 00005E66 0805[F26F0000]      <1> 	or	[active], al
  2688                              <1> 		; bis $2,active / set disk busy bit
  2689                              <1> 	;push	ax
  2690                              <1> 	; 24/12/2021
  2691 00005E6C 50                  <1> 	push	eax
  2692 00005E6D E8CA000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2693                              <1> 	;mov    [edi+drv.error], ah
  2694                              <1> 	; 24/12/2021
  2695 00005E72 58                  <1> 	pop	eax
  2696                              <1> 	;pop	ax
  2697 00005E73 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2698                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2699                              <1> 	;jna	short poke_4
  2700                              <1> 		; tstb deverr(r3) / test for errors on this device
  2701                              <1>        		; beq 3f / branch if no errors
  2702                              <1> 	; 02/07/2015 (32 bit modification)
  2703                              <1> 	; 20/07/2013
  2704 00005E75 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2705                              <1>        		; mov $-1,2(r1) / destroy associativity
  2706 00005E7C 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2707                              <1> 		; clrb 1(r1) / do not do I/O
  2708 00005E81 EB26                <1> 	jmp     short poke_5
  2709                              <1> poke_4:	; 20/07/2013
  2710                              <1> 	; 17/07/2013
  2711 00005E83 F6D0                <1> 	not 	al 
  2712 00005E85 2005[F26F0000]      <1> 	and	[active], al ; reset, not busy
  2713                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2714                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2715 00005E8B 668B03              <1> 	mov	ax, [ebx]
  2716                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2717 00005E8E 66250006            <1>         and	ax, 600h
  2718                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2719 00005E92 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2720                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2721 00005E97 C0E403              <1> 	shl	ah, 3
  2722                              <1>        		; rol r3
  2723                              <1>                 ; rol r3
  2724                              <1>                 ; rol r3	
  2725 00005E9A 660903              <1> 	or	[ebx], ax
  2726                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2727                              <1> 			   ; bits 12 and 13
  2728 00005E9D E8ABF1FFFF          <1> 	call	idle ; 18/01/2014
  2729                              <1> 	;; sti
  2730                              <1> 	;hlt 	; wait for a hardware interrupt
  2731                              <1> 	;; cli
  2732                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2733                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2734                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2735                              <1> 	; method, this procedure will wait for a time according to
  2736                              <1> 	; multi tasking and time sharing concept.
  2737                              <1> 	;
  2738                              <1> 	; 24/10/2015
  2739                              <1> 	;not	ax 
  2740 00005EA2 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2741 00005EA6 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2742                              <1> poke_5: ;2:
  2743 00005EA9 81FE[CA6F0000]      <1>         cmp     esi, bufp
  2744                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2745                              <1>                             ; / has been scanned
  2746 00005EAF 778F                <1> 	ja      short poke_1
  2747                              <1>                ; bhi 1b
  2748                              <1> 	; 24/03/2013
  2749                              <1>        		; mov (sp)+,r3
  2750                              <1>        		; mov (sp)+,r2
  2751                              <1>        		; mov (sp)+,r1
  2752 00005EB1 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2753 00005EB2 5B                  <1> 	pop 	ebx
  2754                              <1> 	; 02/07/2015 (32 bit modification)
  2755                              <1> 	; 20/07/2013
  2756                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2757 00005EB3 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2758                              <1> 	;	
  2759                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2760                              <1> 	; or written succesfully; even if an error occurs while
  2761                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2762                              <1> 	;
  2763                              <1> 	; 09/06/2015
  2764 00005EB6 F5                  <1> 	cmc
  2765 00005EB7 C3                  <1> 	retn
  2766                              <1>                 ; rts r0
  2767                              <1> 
  2768                              <1> bufaloc:
  2769                              <1> 	; 20/08/2015
  2770                              <1> 	; 19/08/2015
  2771                              <1> 	; 02/07/2015
  2772                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2773                              <1> 	;	     (32 bit modifications)	
  2774                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2775                              <1> 	;
  2776                              <1> 	; bufaloc - Block device I/O buffer allocation
  2777                              <1> 	; 
  2778                              <1> 	; INPUTS ->
  2779                              <1> 	;    r1 - block number
  2780                              <1> 	;    cdev - current (block/disk) device number
  2781                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2782                              <1> 	; OUTPUTS ->
  2783                              <1> 	;    r5 - pointer to buffer allocated
  2784                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2785                              <1> 	;
  2786                              <1> 	; ((AX = R1)) input/output
  2787                              <1> 	; ((BX = R5)) output
  2788                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2789                              <1> 	;    zf=1 -> block already in a I/O buffer
  2790                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2791                              <1> 	;    ((DL = Device ID))
  2792                              <1> 	;    (((DH = 0 or 1)))
  2793                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2794                              <1> 	;    ((CX and DH will not be used after return)))
  2795                              <1> 
  2796                              <1> 	;;push 	esi ; ***
  2797                              <1> 		; mov r2,-(sp) / save r2 on stack
  2798                              <1>        		; mov $340,*$ps / set processor priority to 7
  2799                              <1> 	; 20/07/2013
  2800                              <1> 	; 26/04/2013
  2801 00005EB8 0FB61D[EE6F0000]    <1> 	movzx	ebx, byte [cdev] ; 0 or 1
  2802 00005EBF BF[F06F0000]        <1> 	mov	edi, rdev  ; offset mdev = offset rdev + 1
  2803 00005EC4 01DF                <1> 	add	edi, ebx
  2804                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2805                              <1> 			;; eDI points to device id.
  2806 00005EC6 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2807                              <1> 	; 11/06/20215
  2808 00005EC9 80BB[2A670000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2809 00005ED0 720F                <1> 	jb	short bufaloc_9
  2810 00005ED2 C705[5D700000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2810 00005EDA 0000                <1>
  2811 00005EDC E9A4DDFFFF          <1> 	jmp	error
  2812                              <1> bufaloc_9:
  2813 00005EE1 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2814                              <1> bufaloc_10: ; 02/07/2015
  2815 00005EE3 31ED                <1> 	xor 	ebp, ebp ; 0
  2816 00005EE5 55                  <1> 	push	ebp ; 0
  2817 00005EE6 89E5                <1>         mov     ebp, esp	
  2818                              <1> 	;
  2819                              <1> bufaloc_1: ;1:
  2820                              <1> 		; clr -(sp) / vacant buffer
  2821 00005EE8 BE[CA6F0000]        <1>         mov 	esi, bufp
  2822                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2823                              <1> 			     ; / entrys in buffer area
  2824                              <1> bufaloc_2: ;2:
  2825 00005EED 8B1E                <1> 	mov	ebx, [esi]
  2826                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2827                              <1> 			    ; queue entry into r5
  2828 00005EEF 66F70300F6          <1> 	test	word [ebx], 0F600h
  2829                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2830 00005EF4 7503                <1>         jnz	short bufaloc_3
  2831                              <1> 		; bne 3f / branch when 
  2832                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2833                              <1>                        ; / (i.e., buffer busy)
  2834 00005EF6 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2835                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2836                              <1> 			; / found points to word 2 of I/O queue entry)
  2837                              <1> bufaloc_3: ;3:
  2838                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2839                              <1> 	;
  2840 00005EF9 3813                <1> 	cmp	[ebx], dl	
  2841                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2842                              <1> 			       ; / as current device
  2843 00005EFB 7508                <1> 	jne	short bufaloc_4
  2844                              <1>        		; bne 3f
  2845 00005EFD 394304              <1> 	cmp	[ebx+4], eax
  2846                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2847                              <1> 			     ; / same as current block number
  2848 00005F00 7503                <1>        	jne	short bufaloc_4
  2849                              <1> 		; bne 3f
  2850                              <1> 	;add	esp, 4
  2851 00005F02 59                  <1> 	pop	ecx
  2852                              <1>        		; tst (sp)+ / bump stack pointer
  2853 00005F03 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2854                              <1> 				; jump to bufaloc_6 in original Unix v1
  2855                              <1>        		; br 1f / use this buffer
  2856                              <1> bufaloc_4: ;3:
  2857 00005F05 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2858                              <1> 	;
  2859 00005F08 81FE[E26F0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2860                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2861 00005F0E 72DD                <1> 	jb	short bufaloc_2
  2862                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2863                              <1>                        ; / buffers not checked)
  2864 00005F10 5E                  <1>         pop	esi
  2865                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2866                              <1> 			     ; / to last free block
  2867 00005F11 09F6                <1>        	or	esi, esi 
  2868 00005F13 7507                <1> 	jnz	short bufaloc_5
  2869                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2870                              <1> 	        ; / if a free buffer is found branch to 2f
  2871                              <1>         ;; mov  ecx, [s.wait_]
  2872 00005F15 E833F1FFFF          <1> 	call	idle
  2873                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2874 00005F1A EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  2875                              <1>        		; br 1b
  2876                              <1> bufaloc_5: ;2:
  2877                              <1> 		; tst (r0)+ / skip if warmed over buffer
  2878 00005F1C FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  2879                              <1> bufaloc_6: ;1:
  2880 00005F1E 8B1E                <1>         mov    	ebx, [esi] 
  2881                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  2882                              <1> 			     ; / entry in r5
  2883                              <1> 	;; 26/04/2013
  2884                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  2885 00005F20 8813                <1> 	mov 	[ebx], dl
  2886                              <1> 		; movb cdev,(r5) / put current device number 
  2887                              <1> 				 ; / in I/O queue entry
  2888 00005F22 894304              <1> 	mov 	[ebx+4], eax
  2889                              <1> 		; mov r1,2(r5) / move block number into word 2 
  2890                              <1> 			     ; / of I/O queue entry
  2891                              <1> bufaloc_7: ;1:
  2892 00005F25 81FE[CA6F0000]      <1>         cmp	esi, bufp
  2893                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  2894                              <1> 			     ; / and put latest assigned
  2895 00005F2B 760A                <1> 	jna	short bufaloc_8	
  2896                              <1>        		; blos 1f / buffer on the top 
  2897                              <1> 			; / (this makes if the lowest priority)
  2898 00005F2D 83EE04              <1> 	sub	esi, 4
  2899 00005F30 8B0E                <1> 	mov	ecx, [esi]
  2900 00005F32 894E04              <1> 	mov	[esi+4], ecx
  2901                              <1> 		; mov -(r2),2(r2) / job for a particular device
  2902 00005F35 EBEE                <1> 	jmp 	short bufaloc_7        
  2903                              <1> 		; br 1b
  2904                              <1> bufaloc_8: ;1:
  2905 00005F37 891E                <1>         mov	[esi], ebx
  2906                              <1> 		; mov r5,(r2)
  2907                              <1> 	;;pop	esi ; ***
  2908                              <1>        		; mov (sp)+,r2 / restore r2
  2909 00005F39 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  2910                              <1> 		; Retro UNIX 8086 v1 modification
  2911                              <1> 		; zf=1 --> block already is in an I/O buffer
  2912                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  2913 00005F3B C3                  <1> 	retn
  2914                              <1> 		; rts r0
  2915                              <1> 
  2916                              <1> diskio:
  2917                              <1> 	; 10/07/2015
  2918                              <1> 	; 02/07/2015
  2919                              <1> 	; 16/06/2015
  2920                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2921                              <1> 	;	     (80386 protected mode modifications)	
  2922                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2923                              <1> 	;
  2924                              <1> 	; Retro UNIX 8086 v1 feature only !
  2925                              <1> 	;
  2926                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  2927                              <1> 	; 04/07/2009 - 20/07/2011
  2928                              <1> 	;
  2929                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  2930                              <1> 	;
  2931                              <1>         ; INPUTS ->
  2932                              <1> 	; 	   eBX = System I/O Buffer header address
  2933                              <1> 	;
  2934                              <1>         ; OUTPUTS -> cf=0 --> done 
  2935                              <1> 	; 	     cf=1 ---> error code in AH
  2936                              <1> 	;
  2937                              <1> 	; (Modified registers: eAX, eCX, eDX)
  2938                              <1> 	
  2939                              <1> ;rw_disk_sector:
  2940                              <1> 	; 10/07/2015
  2941                              <1> 	; 02/07/2015
  2942                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  2943                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  2944                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  2945                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  2946                              <1> 	;
  2947                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  2948 00005F3C B602                <1> 	mov	dh, 2
  2949 00005F3E 668B03              <1> 	mov	ax, [ebx] 
  2950                              <1> 	;
  2951 00005F41 56                  <1> 	push	esi ; ****
  2952 00005F42 53                  <1> 	push	ebx ; ***
  2953                              <1> 	;
  2954 00005F43 0FB6C8              <1> 	movzx	ecx, al
  2955 00005F46 89CE                <1> 	mov	esi, ecx
  2956                              <1> 	;
  2957 00005F48 38F1                <1> 	cmp	cl, dh ; 2
  2958 00005F4A 7202                <1> 	jb	short rwdsk0
  2959 00005F4C 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  2960                              <1> rwdsk0:
  2961 00005F4E A2[DB660000]        <1> 	mov	[drv], al
  2962 00005F53 81C6[2A670000]      <1> 	add	esi, drv.status
  2963                              <1> 	; 11/06/2015
  2964 00005F59 803EF0              <1> 	cmp	byte [esi], 0F0h 
  2965 00005F5C 720F                <1> 	jb      short rwdsk1
  2966                              <1> 	; 'drive not ready' error
  2967 00005F5E C705[5D700000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2967 00005F66 0000                <1>
  2968 00005F68 E918DDFFFF          <1> 	jmp	error
  2969                              <1> rwdsk1:
  2970 00005F6D F6C402              <1> 	test	ah, 2
  2971                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  2972                              <1> 			   ; write bit
  2973 00005F70 7402                <1> 	jz	short rwdsk2
  2974                              <1> 	;test	ah, 4
  2975                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  2976                              <1> 	;		 ; read bit
  2977                              <1> 	;jz	short diskio_ret
  2978 00005F72 FEC6                <1> 	inc	dh ; 03h = write
  2979                              <1> rwdsk2:
  2980 00005F74 88C2                <1> 	mov	dl, al
  2981 00005F76 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  2982 00005F79 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  2983 00005F7B C0E102              <1> 	shl	cl, 2
  2984 00005F7E 81C1[0E670000]      <1> 	add	ecx, drv.size ; disk size
  2985 00005F84 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  2986 00005F86 720F                <1> 	jb      short rwdsk3
  2987                              <1>  	; 'out of volume' error
  2988 00005F88 C705[5D700000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE 	
  2988 00005F90 0000                <1>
  2989 00005F92 E9EEDCFFFF          <1> 	jmp	error
  2990                              <1> rwdsk3:
  2991                              <1> 	; 11/06/2015
  2992 00005F97 83C304              <1> 	add	ebx, 4 ; buffer address
  2993 00005F9A C605[8E700000]04    <1> 	mov	byte [retry_count], 4
  2994 00005FA1 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  2995 00005FA4 7432                <1>         jz      short rwdsk_chs
  2996                              <1> rwdsk_lba:
  2997                              <1> 	; LBA read/write (with private LBA function) 
  2998                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  2999 00005FA6 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3000 00005FA9 89C1                <1> 	mov	ecx, eax ; sector number
  3001                              <1> 	; ebx = buffer (data) address
  3002                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3003                              <1> rwdsk_lba_retry:
  3004                              <1> 	;mov	dl, [drv]
  3005                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3006 00005FAB B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3007 00005FAD 00F4                <1> 	add	ah, dh		
  3008 00005FAF B001                <1> 	mov	al, 1
  3009                              <1> 	;int	13h
  3010 00005FB1 E869C7FFFF          <1> 	call	int13h
  3011 00005FB6 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3012 00005FB8 730E                <1> 	jnc	short rwdsk_lba_ok
  3013 00005FBA 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3014 00005FBD 7408                <1>         je      short rwdsk_lba_fails
  3015 00005FBF FE0D[8E700000]      <1> 	dec	byte [retry_count]
  3016 00005FC5 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3017                              <1> rwdsk_lba_fails:
  3018 00005FC7 F9                  <1> 	stc
  3019                              <1> rwdsk_lba_ok:
  3020 00005FC8 5B                  <1> 	pop	ebx ; ***
  3021 00005FC9 5E                  <1> 	pop	esi ; ****
  3022 00005FCA C3                  <1> 	retn
  3023                              <1> rwdsk_lba_reset:
  3024 00005FCB B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3025                              <1> 	;int	13h
  3026 00005FCD E84DC7FFFF          <1>         call	int13h
  3027 00005FD2 73D7                <1> 	jnc     short rwdsk_lba_retry
  3028 00005FD4 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3029 00005FD6 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3030                              <1> 	;
  3031                              <1> 	; CHS read (convert LBA address to CHS values)	
  3032                              <1> rwdsk_chs:
  3033                              <1> 	; 10/07/2015
  3034 00005FD8 81EE[2A670000]      <1> 	sub	esi, drv.status
  3035 00005FDE 89F1                <1> 	mov	ecx, esi
  3036 00005FE0 81C6[31670000]      <1> 	add 	esi, drv.error
  3037                              <1> 	; 02/07/2015
  3038                              <1> 	; 16/06/2015
  3039                              <1>  	; 11/06/2015 
  3040 00005FE6 53                  <1> 	push	ebx ; ** ; buffer
  3041 00005FE7 D1E1                <1> 	shl	ecx, 1
  3042 00005FE9 51                  <1> 	push	ecx ; * 
  3043                              <1> 	;
  3044 00005FEA 89CB                <1> 	mov	ebx, ecx
  3045 00005FEC 8835[8D700000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3046 00005FF2 31D2                <1> 	xor	edx, edx ; 0
  3047 00005FF4 29C9                <1> 	sub	ecx, ecx 
  3048 00005FF6 81C3[00670000]      <1>         add     ebx, drv.spt
  3049 00005FFC 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3050                              <1> 		; EDX:EAX = LBA
  3051 00005FFF F7F1                <1> 	div	ecx
  3052 00006001 88D1                <1> 	mov	cl, dl	; sector number - 1
  3053 00006003 FEC1                <1> 	inc	cl	; sector number (1 based)
  3054 00006005 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3055 00006006 6651                <1> 	push	cx
  3056 00006008 81C3[F2660000]      <1>         add     ebx, drv.heads
  3057 0000600E 668B0B              <1> 	mov	cx, [ebx] ; heads
  3058 00006011 31D2                <1> 	xor	edx, edx
  3059                              <1> 		; EAX = cylinders * heads + head
  3060 00006013 F7F1                <1> 	div	ecx
  3061 00006015 6659                <1> 	pop	cx     ; sector number
  3062 00006017 88D6                <1> 	mov	dh, dl ; head number
  3063 00006019 8A15[DB660000]      <1> 	mov	dl, [drv]
  3064 0000601F 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3065 00006021 C0E406              <1> 	shl	ah, 6
  3066 00006024 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3067                              <1> 		       ; sector (bits 0-7)
  3068 00006026 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3069                              <1> 		; CL = sector (bits 0-5)
  3070                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3071                              <1> 		; CH = cylinder (bits 0-7)
  3072                              <1> 		; DH = head
  3073                              <1> 		; DL = drive
  3074                              <1> 	;
  3075 00006027 C605[8E700000]04    <1> 	mov	byte [retry_count], 4
  3076                              <1> rwdsk_retry:	
  3077 0000602E 8A25[8D700000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3078 00006034 B001                <1> 	mov	al, 1 ; sector count	
  3079                              <1> 	;int	13h
  3080 00006036 E8E4C6FFFF          <1> 	call	int13h
  3081 0000603B 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3082 0000603D 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3083 0000603F 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3084 00006042 7408                <1> 	je	short rwdsk_fails
  3085 00006044 FE0D[8E700000]      <1> 	dec	byte [retry_count]
  3086 0000604A 7504                <1> 	jnz	short rwdsk_reset
  3087                              <1> rwdsk_fails:
  3088 0000604C F9                  <1> 	stc
  3089                              <1> rwdsk_ok:
  3090 0000604D 5B                  <1> 	pop	ebx ; ***
  3091 0000604E 5E                  <1> 	pop	esi ; ****
  3092 0000604F C3                  <1> 	retn
  3093                              <1> rwdsk_reset:
  3094                              <1> 	; 02/02/2015
  3095 00006050 28E4                <1> 	sub	ah, ah
  3096 00006052 80FA80              <1> 	cmp	dl, 80h
  3097 00006055 7202                <1> 	jb	short rwdsk_fd_reset
  3098 00006057 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3099                              <1> rwdsk_fd_reset:
  3100                              <1> 	;int	13h
  3101 00006059 E8C1C6FFFF          <1>         call	int13h
  3102 0000605E 73CE                <1> 	jnc	short rwdsk_retry
  3103 00006060 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3104 00006062 EBE9                <1> 	jmp 	short rwdsk_ok
  3105                              <1> 
  3106                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3107                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3108                              <1> ;
  3109                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3110                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3111                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3112                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3113                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3114                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3115                              <1> ; as in original unix v1.
  3116                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3117                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3118                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3119                              <1> ;
  3120                              <1> ; Erdogan tan (10/07/2015) 
  3121                              <1> 
  3122                              <1> ;drum: / interrupt handler
  3123                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3124                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3125                              <1> ;                                      / error
  3126                              <1> ;               br 3f / no, error
  3127                              <1> ;       br      2f / error
  3128                              <1> ;
  3129                              <1> ;disk:
  3130                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3131                              <1> ;       jmp     *$0f
  3132                              <1> ;0:
  3133                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3134                              <1> ;      	        br 3f / no, errors
  3135                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3136                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3137                              <1> ;                        / to 1f
  3138                              <1> ;       br      4f
  3139                              <1> ;1:
  3140                              <1> ;       bit     $20000,rkcs
  3141                              <1> ;       beq     4f / wait for seek complete
  3142                              <1> ;       mov     $0b,0b-2
  3143                              <1> ;       mov     rkap,r1
  3144                              <1> ;2:
  3145                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3146                              <1> ;                          / the disk buffer
  3147                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3148                              <1> ;       inc     r1
  3149                              <1> ;       asr     (r1)
  3150                              <1> ;       asr     (r1)
  3151                              <1> ;       asr     (r1) / reissue request
  3152                              <1> ;       dec     r1
  3153                              <1> ;3:
  3154                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3155                              <1> ;       mov     ac,-(sp)
  3156                              <1> ;       mov     mq,-(sp) / put these on the stack
  3157                              <1> ;       mov     sc,-(sp)
  3158                              <1> ;       jsr     r0,poke
  3159                              <1> ;       mov     (sp)+,sc
  3160                              <1> ;       mov     (sp)+,mq / pop them off stack
  3161                              <1> ;       mov     (sp)+,ac
  3162                              <1> ;4:
  3163                              <1> ;       jmp     retisp / u4-3
  3164                              <1> ;
  3165                              <1> ;trapt:                  / r2 points to the
  3166                              <1> ;       mov     (r0)+,r2 / device control register
  3167                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3168                              <1> ;       tst     (sp)+
  3169                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3170                              <1> ;       bge     4b / device still active so branch
  3171                              <1> ;       bit     (r0),active / was device busy?
  3172                              <1> ;       beq     4b / no, stray interrupt
  3173                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3174                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3175                              <1> ;       bge     2f / if no error jump to 2f
  3176                              <1> ;       tst     (r0)+ / skip on error
  3177                              <1> ; 2:
  3178                              <1> ;       jmp     (r0)
  2001                                  %include 'u9.s'        ; 29/06/2015
  2002                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS9.INC
  2003                              <1> ; Last Modification: 24/12/2021
  2004                              <1> ; ----------------------------------------------------------------------------
  2005                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2006                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2007                              <1> ;
  2008                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2009                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2010                              <1> ; <Bell Laboratories (17/3/1972)>
  2011                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2012                              <1> ;
  2013                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2014                              <1> ;
  2015                              <1> ; ****************************************************************************
  2016                              <1> 
  2017                              <1> getch:
  2018                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2019                              <1> 	; 30/06/2015
  2020                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2021 00006064 28C0                <1> 	sub	al, al ; 0
  2022                              <1> getch_q: ; 06/08/2015
  2023 00006066 8A25[566C0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2024 0000606C EB06                <1>         jmp     short getc_n
  2025                              <1> 
  2026                              <1> getc: 
  2027                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2028                              <1> 	; 12/11/2015
  2029                              <1> 	; 15/09/2015
  2030                              <1> 	; 01/07/2015
  2031                              <1> 	; 30/06/2015
  2032                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2033                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2034                              <1> 	;
  2035                              <1> 	; Retro UNIX 8086 v1 modification !
  2036                              <1> 	; 
  2037                              <1> 	; 'getc' gets (next) character 
  2038                              <1> 	;	 from requested TTY (keyboard) buffer 
  2039                              <1> 	; INPUTS ->
  2040                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2041                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2042                              <1> 	;	(Keyboard buffer will point to 
  2043                              <1> 	;			next character at next call)
  2044                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2045                              <1> 	;	(Keyboard buffer will point to 
  2046                              <1> 	;			current character at next call)
  2047                              <1> 	; OUTPUTS ->
  2048                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2049                              <1> 	;     			 ZF=0 -> AX has (current) character
  2050                              <1> 	;      AL = ascii code
  2051                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2052                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2053                              <1> 	; Original UNIX V1 'getc': 
  2054                              <1> 	;		get a character off character list
  2055                              <1> 	;
  2056                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2057                              <1> 	;
  2058                              <1> 	; 30/06/20045 (32 bit modifications)
  2059                              <1> 	; 16/07/2013
  2060                              <1> 	; mov 	[getctty], ah
  2061                              <1> 	;
  2062                              <1> 
  2063 0000606E 8A25[5C700000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2064                              <1> getc_n:
  2065                              <1> 	; 30/06/2015
  2066 00006074 08E4                <1> 	or	ah, ah
  2067 00006076 740D                <1> 	jz	short getc0 
  2068 00006078 D0E4                <1> 	shl	ah, 1
  2069 0000607A 0FB6DC              <1> 	movzx	ebx, ah
  2070 0000607D 81C3[586C0000]      <1> 	add	ebx, ttychr
  2071 00006083 EB05                <1> 	jmp	short getc1
  2072                              <1> getc0:
  2073 00006085 BB[586C0000]        <1> 	mov	ebx, ttychr
  2074                              <1> getc1:
  2075 0000608A 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2076                              <1> 				; (by kb_int)	
  2077 0000608D 6609C9              <1> 	or	cx, cx
  2078 00006090 7507                <1> 	jnz	short getc2
  2079 00006092 20C0                <1> 	and 	al, al
  2080 00006094 7415                <1> 	jz	short getc_s
  2081                              <1> 	;xor	ax, ax
  2082                              <1> 	; 24/12/2021
  2083 00006096 31C0                <1> 	xor	eax, eax
  2084 00006098 C3                  <1> 	retn
  2085                              <1> getc2:	
  2086 00006099 20C0                <1> 	and	al, al
  2087 0000609B 6689C8              <1> 	mov	ax, cx
  2088 0000609E 66B90000            <1> 	mov	cx, 0
  2089 000060A2 7506                <1> 	jnz	short getc3
  2090                              <1> getc_sn:
  2091 000060A4 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2092 000060A7 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2093                              <1> getc3:
  2094 000060AA C3                  <1> 	retn
  2095                              <1> getc_s:
  2096                              <1> 	; 12/11/2015
  2097                              <1> 	; 15/09/2015
  2098                              <1> 	; 01/07/2015
  2099                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2100                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2101                              <1> 	;
  2102                              <1> 	; tty  of the current process is not 
  2103                              <1> 	; current tty (ptty); so, current process only 
  2104                              <1> 	; can use keyboard input when its tty becomes 
  2105                              <1> 	; current tty (ptty).
  2106                              <1> 	; 'sleep' is for preventing an endless lock
  2107                              <1> 	; during this tty input request.
  2108                              <1> 	; (Because, the user is not looking at the video page
  2109                              <1> 	; of the process to undersand there is a keyboard
  2110                              <1> 	; input request.)
  2111                              <1> 	;
  2112                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2113                              <1> 	;
  2114                              <1> 	; 05/10/2013
  2115                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2116                              <1> 	;
  2117                              <1> 	; 10/10/2013
  2118                              <1> gcw0:
  2119 000060AB B10A                <1> 	mov	cl, 10 ; ch = 0
  2120                              <1> gcw1:	
  2121                              <1> 	; 12/11/2015
  2122 000060AD E8E0DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2123                              <1> 	; 10/10/2013
  2124 000060B2 E896EFFFFF          <1> 	call	idle
  2125 000060B7 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2126                              <1> 				; (by kb_int)
  2127 000060BA 6609C0              <1> 	or	ax, ax
  2128                              <1> ;	jnz	short gcw3
  2129 000060BD 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2130                              <1> 	; 30/06/2015
  2131 000060BF FEC9                <1> 	dec	cl
  2132 000060C1 75EA                <1> 	jnz	short gcw1
  2133                              <1> 	;
  2134 000060C3 8A25[5C700000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2135                              <1> ;	; 10/12/2013
  2136                              <1> ;	cmp 	ah, [ptty]
  2137                              <1> ;	jne	short gcw2
  2138                              <1> ;	; 14/02/2014
  2139                              <1> ;	cmp	byte [u.uno], 1
  2140                              <1> ;	jna	short gcw0		
  2141                              <1> ;gcw2:
  2142 000060C9 E812F0FFFF          <1> 	call	sleep
  2143                              <1> 	;
  2144                              <1> 	; 20/09/2013
  2145 000060CE 8A25[5C700000]      <1> 	mov	ah, [u.ttyn]
  2146 000060D4 30C0                <1> 	xor 	al, al
  2147 000060D6 EB9C                <1> 	jmp	short getc_n
  2148                              <1> ;gcw3:
  2149                              <1> gcw2: 	; 15/09/2015
  2150                              <1> 	; 10/10/2013
  2151 000060D8 30C9                <1> 	xor	cl, cl
  2152 000060DA EBC8                <1> 	jmp	short getc_sn
  2153                              <1> 
  2154                              <1> putc:	
  2155                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2156                              <1> 	; 13/08/2015
  2157                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2158                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2159                              <1> 	;
  2160                              <1> 	; Retro UNIX 8086 v1 modification !
  2161                              <1> 	; 
  2162                              <1> 	; 'putc' puts a character 
  2163                              <1> 	;	 onto requested (tty) video page or
  2164                              <1> 	;	 serial port
  2165                              <1> 	; INPUTS ->
  2166                              <1> 	;     AL = ascii code of the character
  2167                              <1> 	;     AH = video page (tty) number (0 to 7)
  2168                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2169                              <1> 	; OUTPUTS ->
  2170                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2171                              <1> 	;      			ZF=0 -> AX has (current) character
  2172                              <1> 	;     cf=0 and AH = 0 -> no error
  2173                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2174                              <1> 	; 
  2175                              <1> 	; Original UNIX V1 'putc': 
  2176                              <1> 	;     put a character at the end of character list
  2177                              <1> 	;
  2178                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2179                              <1> 	;
  2180 000060DC 80FC07              <1> 	cmp	ah, 7
  2181                              <1>         ;ja	sndc
  2182 000060DF 770A                <1>         ja      short sndc ; 24/12/2024
  2183                              <1> 	; 30/06/2015
  2184 000060E1 0FB6DC              <1> 	movzx	ebx, ah
  2185                              <1> 	; 13/08/2015
  2186 000060E4 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2187 000060E6 E99DB3FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2188                              <1> 
  2189                              <1> sndc:   ; <Send character>
  2190                              <1> 	;
  2191                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2192                              <1> 	; 17/11/2015
  2193                              <1> 	; 16/11/2015
  2194                              <1> 	; 11/11/2015
  2195                              <1> 	; 10/11/2015
  2196                              <1> 	; 09/11/2015
  2197                              <1> 	; 08/11/2015
  2198                              <1> 	; 07/11/2015
  2199                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2200                              <1> 	; 29/10/2015
  2201                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2202                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2203                              <1> 	;
  2204                              <1> 	; Retro UNIX 8086 v1 feature only !
  2205                              <1> 	;
  2206                              <1> 	; ah = [u.ttyn]
  2207                              <1> 	;
  2208                              <1> 	; 30/06/2015
  2209 000060EB 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2210                              <1> 	; 07/11/2015
  2211 000060EE 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2212                              <1> sndc0:
  2213                              <1> 	; 07/11/2015
  2214 000060F1 E840F0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2215 000060F6 7405                <1> 	jz	short sndc1
  2216 000060F8 E895DCFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2217                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2218                              <1> sndc1:
  2219                              <1> 	; 16/11/2015
  2220                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2221                              <1> 	; 24/12/2021
  2222 000060FD 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2223                              <1> sndcx:
  2224 000060FF 8A83[9A6C0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2225 00006105 8AA3[986C0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2226                              <1> 	;
  2227                              <1> 	; 17/11/2015
  2228                              <1> 	; check 'request for response' status
  2229 0000610B 80BB[946C0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2230 00006112 740A                <1> 	jz	short query
  2231                              <1> response:
  2232 00006114 FE05[976C0000]      <1> 	inc 	byte [comqr] ; query or response status
  2233 0000611A B0FF                <1> 	mov	al, 0FFh	 
  2234 0000611C EB14                <1> 	jmp	short sndc3
  2235                              <1> query:
  2236 0000611E 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2237 00006120 750E                <1> 	jnz 	short sndc2 ; normal character
  2238                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2239                              <1> 	;je	short sndc2  ; yes, already responded
  2240                              <1> 	; 16/11/2015
  2241                              <1> 	; query: request for response (again)
  2242 00006122 8883[986C0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2243 00006128 FE05[976C0000]      <1> 	inc 	byte [comqr] ; query or response status
  2244 0000612E EB02                <1> 	jmp	short sndc3
  2245                              <1> sndc2:
  2246 00006130 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2247                              <1> sndc3:
  2248 00006132 8883[9A6C0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2249 00006138 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2250                              <1> 	; 30/06/2015
  2251 0000613A E8E9D5FFFF          <1> 	call	sp_status ; get serial port status
  2252                              <1> 	; AL = Line status, AH = Modem status
  2253                              <1> 	; 07/11/2015
  2254 0000613F A880                <1> 	test	al, 80h
  2255 00006141 7504                <1> 	jnz	short sndc4
  2256 00006143 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2257 00006145 751B                <1> 	jnz	short sndc5
  2258                              <1> sndc4: 	; Check line status again
  2259                              <1> 	; 16/11/2015
  2260                              <1> 	;push	cx
  2261                              <1> 	; 24/12/2021
  2262 00006147 51                  <1> 	push	ecx
  2263 00006148 B906000000          <1> 	mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2264 0000614D E845B4FFFF          <1> 	call	WAITF
  2265                              <1> 	;pop	cx
  2266                              <1> 	; 24/12/1021
  2267 00006152 59                  <1> 	pop	ecx
  2268                              <1> 	;
  2269 00006153 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2270 00006155 E8CED5FFFF          <1> 	call	sp_status ; get serial port status
  2271                              <1> 	; 16/11/2015
  2272                              <1> 	; 09/11/2015
  2273                              <1> 	; 08/11/2015
  2274 0000615A A880                <1> 	test	al, 80h	; time out error
  2275 0000615C 7566                <1>         jnz     short sndc7
  2276 0000615E A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2277 00006160 7462                <1>         jz	short sndc7
  2278                              <1> sndc5:  
  2279 00006162 8A83[9A6C0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2280 00006168 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2281 0000616C 28DE                <1> 	sub	dh, bl
  2282 0000616E EE                  <1> 	out	dx, al	   ; send on serial port
  2283                              <1> 	; 10/11/2015
  2284                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2285                              <1> 	; (to improve text flow to the terminal)
  2286                              <1> 	; ('diskette.inc': 'WAITF')
  2287                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2288                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2289                              <1> 	;push	cx
  2290                              <1> 	; 24/12/2021
  2291 0000616F 51                  <1> 	push	ecx
  2292 00006170 B906000000          <1> 	mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2293 00006175 E81DB4FFFF          <1> 	call	WAITF
  2294                              <1> 	;pop	cx
  2295                              <1> 	; 24/12/1021
  2296 0000617A 59                  <1> 	pop	ecx
  2297                              <1>     	;
  2298                              <1> 	; 07/11/2015
  2299 0000617B 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2300                              <1> 	;
  2301 0000617D E8A6D5FFFF          <1> 	call	sp_status ; get serial port status
  2302                              <1> 	; AL = Line status, AH = Modem status
  2303                              <1> 	;
  2304 00006182 E8AFEFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2305 00006187 7405                <1> 	jz	short sndc6
  2306 00006189 E804DCFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2307                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2308                              <1> sndc6:
  2309 0000618E 3C80                <1> 	cmp	al, 80h
  2310 00006190 7332                <1> 	jnb	short sndc7		
  2311                              <1> 	;
  2312 00006192 803D[976C0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2313 00006199 7244                <1> 	jb	short sndc8 	; no, normal character
  2314 0000619B 883D[976C0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2315                              <1> 	; 17/11/2015
  2316 000061A1 E8A7EEFFFF          <1> 	call	idle
  2317                              <1> 	;
  2318 000061A6 38BB[9A6C0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2319                              <1>         ;ja	sndc2       ; response (will be followed by
  2320                              <1> 			    ; a normal character)
  2321                              <1> 	; 24/12/2021
  2322 000061AC 7602                <1> 	jna	short sndc_10
  2323 000061AE EB80                <1> 	jmp	sndc2
  2324                              <1> sndc_10:
  2325                              <1> 	; Query request must be responded by the terminal
  2326                              <1> 	; before sending a normal character !
  2327 000061B0 53                  <1> 	push	ebx
  2328                              <1> 	;push	cx ; *** cl = character (to be sent)
  2329                              <1> 	; 24/12/2021
  2330 000061B1 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2331 000061B2 8A25[5C700000]      <1> 	mov	ah, [u.ttyn]
  2332 000061B8 E823EFFFFF          <1> 	call	sleep ; this process will be awakened by
  2333                              <1> 		      ; received data available interrupt
  2334                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2335                              <1> 	; 24/12/2021
  2336 000061BD 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2337 000061BE 5B                  <1> 	pop	ebx
  2338 000061BF E93BFFFFFF          <1>         jmp	sndcx
  2339                              <1> sndc7:
  2340                              <1> 	 ; 16/11/2015
  2341 000061C4 803D[976C0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2342 000061CB 7213                <1> 	jb	short sndc9 	; no
  2343                              <1> 	;
  2344 000061CD 88BB[986C0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2345 000061D3 88BB[9A6C0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2346                              <1> 	;
  2347 000061D9 883D[976C0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2348                              <1> sndc8:
  2349 000061DF F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2350                              <1> sndc9:
  2351                              <1> 	; AL = Line status, AH = Modem status
  2352 000061E0 C3                  <1> 	retn
  2353                              <1> 
  2354                              <1> get_cpos:
  2355                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2356                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2357                              <1> 	;
  2358                              <1> 	; INPUT -> bl = video page number
  2359                              <1> 	; RETURN -> dx = cursor position
  2360                              <1> 
  2361 000061E1 53                  <1> 	push	ebx
  2362 000061E2 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2363 000061E5 D0E3                <1> 	shl	bl, 1
  2364 000061E7 81C3[466C0000]      <1> 	add	ebx, cursor_posn
  2365 000061ED 668B13              <1> 	mov	dx, [ebx]
  2366 000061F0 5B                  <1> 	pop	ebx
  2367 000061F1 C3                  <1> 	retn
  2368                              <1> 
  2369                              <1> read_ac_current:
  2370                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2371                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2372                              <1> 	;
  2373                              <1> 	; INPUT -> bl = video page number
  2374                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2375                              <1> 
  2376 000061F2 E80FB4FFFF          <1> 	call 	find_position ; 'video.inc'
  2377                              <1> 	; dx = status port
  2378                              <1> 	; esi = cursor location/address
  2379 000061F7 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2380 000061FD 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2381 00006200 C3                  <1> 	retn
  2382                              <1> 
  2383                              <1> syssleep:
  2384                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2385                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2386                              <1> 	;
  2387                              <1> 	; Retro UNIX 8086 v1 feature only
  2388                              <1> 	; (INPUT -> none)
  2389                              <1> 	;
  2390 00006201 0FB61D[57700000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2391 00006208 8AA3[556D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2392 0000620E E8CDEEFFFF          <1> 	call	sleep
  2393 00006213 E98DDAFFFF          <1> 	jmp	sysret
  2394                              <1> 
  2395                              <1> vp_clr:
  2396                              <1> 	; Reset/Clear Video Page
  2397                              <1> 	;
  2398                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2399                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2400                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2401                              <1> 	;
  2402                              <1> 	; Retro UNIX 8086 v1 feature only !
  2403                              <1> 	;
  2404                              <1> 	; INPUTS -> 
  2405                              <1> 	;   BL = video page number	 
  2406                              <1> 	;
  2407                              <1> 	; OUTPUT ->
  2408                              <1> 	;   none
  2409                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2410                              <1> 	;
  2411                              <1> 	; 04/12/2013
  2412 00006218 28C0                <1> 	sub	al, al
  2413                              <1> 	; al = 0 (clear video page)
  2414                              <1> 	; bl = video page
  2415 0000621A B407                <1> 	mov	ah, 07h
  2416                              <1> 	; ah = 7 (attribute/color)
  2417                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2418                              <1> 	; 24/12/2021
  2419 0000621C 31C9                <1> 	xor	ecx, ecx
  2420 0000621E 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2421 00006222 E809B4FFFF          <1> 	call	scroll_up
  2422                              <1> 	; bl = video page
  2423                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2424                              <1> 	; 24/12/2021
  2425 00006227 31D2                <1> 	xor	edx, edx 
  2426 00006229 E97CB3FFFF          <1> 	jmp 	set_cpos
  2427                              <1> 
  2428                              <1> sysmsg:
  2429                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2430                              <1> 	; 11/11/2015
  2431                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2432                              <1> 	; Print user-application message on user's console tty
  2433                              <1> 	;
  2434                              <1> 	; Input -> EBX = Message address
  2435                              <1> 	;	   ECX = Message length (max. 255)
  2436                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2437                              <1> 	;
  2438 0000622E 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2439                              <1> 	;ja	sysret ; nothing to do with big message size
  2440 00006234 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2441 00006236 08C9                <1> 	or	cl, cl
  2442                              <1> 	;jz	sysret
  2443 00006238 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2444 0000623A 20D2                <1> 	and	dl, dl
  2445 0000623C 7502                <1> 	jnz	short sysmsg0
  2446 0000623E B207                <1> 	mov	dl, 07h ; default color
  2447                              <1> 		; (black background, light gray character)
  2448                              <1> sysmsg0:
  2449 00006240 891D[28700000]      <1> 	mov	[u.base], ebx
  2450 00006246 8815[576C0000]      <1> 	mov	[ccolor], dl ; color attributes
  2451 0000624C 89E5                <1> 	mov	ebp, esp
  2452 0000624E 31DB                <1> 	xor	ebx, ebx ; 0
  2453 00006250 891D[30700000]      <1> 	mov	[u.nread], ebx ; 0
  2454                              <1> 	;
  2455 00006256 381D[6F700000]      <1> 	cmp	[u.kcall], bl ; 0
  2456 0000625C 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2457                              <1> 	;
  2458 0000625E 890D[2C700000]      <1> 	mov	[u.count], ecx
  2459 00006264 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2460                              <1> 	; 24/12/2021
  2461                              <1> 	; (dword alignment for esp)
  2462 00006265 F6C103              <1> 	test	cl, 3
  2463 00006268 7404                <1> 	jz	short sysmsg_7
  2464 0000626A 80C903              <1> 	or	cl, 3
  2465 0000626D 41                  <1> 	inc	ecx
  2466                              <1> sysmsg_7:
  2467 0000626E 29CC                <1> 	sub	esp, ecx
  2468 00006270 89E7                <1> 	mov	edi, esp
  2469 00006272 89E6                <1> 	mov	esi, esp
  2470 00006274 66891D[6D700000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2471                              <1> 	; 11/11/2015
  2472 0000627B 8A25[38700000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2473                              <1> 	; 0 = none
  2474 00006281 FECC                <1> 	dec	ah
  2475 00006283 790C                <1> 	jns	short sysmsg1 
  2476 00006285 8A1D[57700000]      <1> 	mov	bl, [u.uno] ; process number	
  2477 0000628B 8AA3[556D0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2478                              <1> sysmsg1:
  2479 00006291 8825[5C700000]      <1> 	mov	[u.ttyn], ah
  2480                              <1> sysmsg2:
  2481 00006297 E8ADF5FFFF          <1> 	call	cpass
  2482 0000629C 7416                <1> 	jz	short sysmsg5
  2483 0000629E AA                  <1> 	stosb
  2484 0000629F 20C0                <1> 	and	al, al
  2485 000062A1 75F4                <1> 	jnz	short sysmsg2
  2486                              <1> sysmsg3:
  2487 000062A3 80FC07              <1> 	cmp	ah, 7 ; tty number
  2488 000062A6 7711                <1> 	ja	short sysmsg6 ; serial port
  2489 000062A8 E83E000000          <1> 	call	print_cmsg
  2490                              <1> sysmsg4:
  2491 000062AD 89EC                <1> 	mov	esp, ebp	
  2492                              <1> sysmsg8: ; 24/12/2021	
  2493 000062AF E9F1D9FFFF          <1> 	jmp	sysret
  2494                              <1> sysmsg5:
  2495 000062B4 C60700              <1> 	mov	byte [edi], 0
  2496 000062B7 EBEA                <1> 	jmp	short sysmsg3
  2497                              <1> sysmsg6:
  2498 000062B9 8A06                <1> 	mov	al, [esi]
  2499 000062BB E82BFEFFFF          <1> 	call	sndc
  2500 000062C0 72EB                <1> 	jc	short sysmsg4
  2501 000062C2 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2502 000062C5 76E6                <1> 	jna	short sysmsg4
  2503 000062C7 46                  <1> 	inc 	esi
  2504 000062C8 8A25[5C700000]      <1> 	mov	ah, [u.ttyn]
  2505 000062CE EBE9                <1> 	jmp	short sysmsg6
  2506                              <1> 
  2507                              <1> sysmsgk: ; Temporary (01/07/2015)
  2508                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2509                              <1> 	; (ECX -character count- will not be considered)
  2510 000062D0 8B35[28700000]      <1> 	mov	esi, [u.base]
  2511 000062D6 8A25[566C0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2512 000062DC 8825[5C700000]      <1> 	mov	[u.ttyn], ah
  2513 000062E2 C605[6F700000]00    <1> 	mov	byte [u.kcall], 0
  2514 000062E9 EBB8                <1> 	jmp	short sysmsg3
  2515                              <1> 	
  2516                              <1> print_cmsg: 
  2517                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2518                              <1> 	;
  2519                              <1> 	; print message (on user's console tty) 
  2520                              <1> 	;	with requested color
  2521                              <1> 	;
  2522                              <1> 	; INPUTS:
  2523                              <1> 	;	esi = message address
  2524                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2525                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2526                              <1> 	;
  2527 000062EB AC                  <1> 	lodsb
  2528                              <1> pcmsg1:
  2529 000062EC 56                  <1> 	push 	esi
  2530 000062ED 0FB61D[5C700000]    <1>         movzx   ebx, byte [u.ttyn]
  2531 000062F4 8A25[576C0000]      <1> 	mov	ah, [ccolor]
  2532 000062FA E889B1FFFF          <1> 	call 	write_tty
  2533 000062FF 5E                  <1> 	pop	esi
  2534 00006300 AC                  <1> 	lodsb
  2535 00006301 20C0                <1> 	and 	al, al  ; 0
  2536 00006303 75E7                <1> 	jnz 	short pcmsg1
  2537 00006305 C3                  <1> 	retn
  2538                              <1> 
  2539                              <1> sysgeterr:
  2540                              <1> 	; 09/12/2015
  2541                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2542                              <1> 	; Get last error number or page fault count
  2543                              <1> 	; (for debugging)
  2544                              <1> 	;
  2545                              <1> 	; Input -> EBX = return type
  2546                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2547                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2548                              <1> 	;	   FFFFFFFEh = total page fault count
  2549                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2550                              <1> 	;
  2551                              <1> 	; Output -> EAX = last error number or page fault count
  2552                              <1> 	;	   (depending on EBX input)
  2553                              <1> 	; 	
  2554 00006306 21DB                <1> 	and 	ebx, ebx
  2555 00006308 750B                <1> 	jnz	short glerr_2
  2556                              <1> glerr_0:
  2557 0000630A A1[5D700000]        <1> 	mov	eax, [u.error]
  2558                              <1> glerr_1:
  2559 0000630F A3[08700000]        <1> 	mov	[u.r0], eax
  2560 00006314 C3                  <1>  	retn
  2561                              <1> glerr_2:
  2562 00006315 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2563 00006316 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2564 00006318 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2565 00006319 75EF                <1> 	jnz	short glerr_0
  2566 0000631B A1[D8800000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2567 00006320 EBED                <1>         jmp     short glerr_1
  2568                              <1> glerr_3:
  2569 00006322 A1[71700000]        <1> 	mov 	eax, [u.pfcount]
  2570 00006327 EBE6                <1> 	jmp	short glerr_1
  2002                                  
  2003                                  ; 07/03/2015
  2004                                  ; Temporary Code
  2005                                  display_disks:
  2006 00006329 803D[DE660000]00        	cmp 	byte [fd0_type], 0
  2007 00006330 7605                    	jna 	short ddsks1
  2008 00006332 E87D000000              	call	pdskm
  2009                                  ddsks1:
  2010 00006337 803D[DF660000]00        	cmp	byte [fd1_type], 0
  2011 0000633E 760C                    	jna	short ddsks2
  2012 00006340 C605[0B690000]31        	mov	byte [dskx], '1'
  2013 00006347 E868000000              	call	pdskm
  2014                                  ddsks2:
  2015 0000634C 803D[E0660000]00        	cmp	byte [hd0_type], 0
  2016 00006353 7654                    	jna	short ddsk6
  2017 00006355 66C705[09690000]68-     	mov	word [dsktype], 'hd'
  2017 0000635D 64                 
  2018 0000635E C605[0B690000]30        	mov	byte [dskx], '0'
  2019 00006365 E84A000000              	call	pdskm
  2020                                  ddsks3:
  2021 0000636A 803D[E1660000]00        	cmp	byte [hd1_type], 0
  2022 00006371 7636                    	jna	short ddsk6
  2023 00006373 C605[0B690000]31        	mov	byte [dskx], '1'
  2024 0000637A E835000000              	call	pdskm
  2025                                  ddsks4:
  2026 0000637F 803D[E2660000]00        	cmp	byte [hd2_type], 0
  2027 00006386 7621                    	jna	short ddsk6
  2028 00006388 C605[0B690000]32        	mov	byte [dskx], '2'
  2029 0000638F E820000000              	call	pdskm
  2030                                  ddsks5:
  2031 00006394 803D[E3660000]00        	cmp	byte [hd3_type], 0
  2032 0000639B 760C                    	jna	short ddsk6
  2033 0000639D C605[0B690000]33        	mov	byte [dskx], '3'
  2034 000063A4 E80B000000              	call	pdskm
  2035                                  ddsk6:
  2036 000063A9 BE[1A690000]            	mov	esi, nextline
  2037 000063AE E806000000              	call	pdskml
  2038                                  pdskm_ok:
  2039 000063B3 C3                      	retn
  2040                                  pdskm:
  2041 000063B4 BE[07690000]            	mov	esi, dsk_ready_msg
  2042                                  pdskml:	
  2043 000063B9 AC                      	lodsb
  2044 000063BA 08C0                    	or	al, al
  2045 000063BC 74F5                    	jz	short pdskm_ok
  2046 000063BE 56                      	push	esi
  2047 000063BF 31DB                    	xor	ebx, ebx ; 0
  2048                                  			; Video page 0 (bl=0)
  2049 000063C1 B407                    	mov	ah, 07h ; Black background, 
  2050                                  			; light gray forecolor
  2051 000063C3 E8C0B0FFFF              	call	write_tty
  2052 000063C8 5E                      	pop	esi
  2053 000063C9 EBEE                    	jmp	short pdskml
  2054                                  
  2055 000063CB 90<rep 5h>              align 16
  2056                                  
  2057                                  gdt:	; Global Descriptor Table
  2058                                  	; (30/07/2015, conforming cs)
  2059                                  	; (26/03/2015)
  2060                                  	; (24/03/2015, tss)
  2061                                  	; (19/03/2015)
  2062                                  	; (29/12/2013)
  2063                                  	;
  2064 000063D0 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2065                                  	; 18/08/2014
  2066                                  			; 8h kernel code segment, base = 00000000h		
  2067 000063D8 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2068                                  			; 10h kernel data segment, base = 00000000h	
  2069 000063E0 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2070                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2071 000063E8 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2072                                  			; 23h user data segment, base address = 400000h ; CORE
  2073 000063F0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2074                                  			; Task State Segment
  2075 000063F8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2076                                  			       ;  no IO permission in ring 3)
  2077                                  gdt_tss0:
  2078 000063FA 0000                    	dw 0  ; TSS base address, bits 0-15 
  2079                                  gdt_tss1:
  2080 000063FC 00                      	db 0  ; TSS base address, bits 16-23 
  2081                                  	      		; 49h	
  2082 000063FD E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2083 000063FE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2084                                  gdt_tss2:
  2085 000063FF 00                      	db 0  ; TSS base address, bits 24-31 
  2086                                  
  2087                                  gdt_end:
  2088                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2089                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2090                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2091                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2092                                  
  2093                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2094                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2095                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2096                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2097                                  		; W= Writeable, A= Accessed
  2098                                  	
  2099                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2100                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2101                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2102                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2103                                  
  2104                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2105                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2106                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2107                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2108                                  	
  2109                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2110                                  
  2111                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2112                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2113                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2114                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2115                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2116                                  		; AVL= Available to programmers	
  2117                                  
  2118                                  gdtd:
  2119 00006400 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2120 00006402 [D0630000]                      dd gdt			; Address of the GDT
  2121                                  
  2122                                  	; 20/08/2014
  2123                                  idtd:
  2124 00006406 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2125 00006408 [C0690000]                      dd idt			; Address of the IDT
  2126                                  
  2127                                  Align 4
  2128                                  
  2129                                  	; 21/08/2014
  2130                                  ilist:
  2131                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2132                                  	;
  2133                                  	; Exception list
  2134                                  	; 25/08/2014	
  2135 0000640C [E9080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2136 00006410 [F0080000]              	dd	exc1	
  2137 00006414 [F7080000]              	dd 	exc2	
  2138 00006418 [FE080000]              	dd	exc3	
  2139 0000641C [02090000]              	dd	exc4	
  2140 00006420 [06090000]              	dd	exc5	
  2141 00006424 [0A090000]              	dd 	exc6	; 06h,  Invalid Opcode
  2142 00006428 [0E090000]              	dd	exc7	
  2143 0000642C [12090000]              	dd	exc8	
  2144 00006430 [16090000]              	dd	exc9	
  2145 00006434 [1A090000]              	dd 	exc10	
  2146 00006438 [1E090000]              	dd	exc11
  2147 0000643C [22090000]              	dd	exc12
  2148 00006440 [26090000]              	dd	exc13	; 0Dh, General Protection Fault
  2149 00006444 [2A090000]              	dd 	exc14	; 0Eh, Page Fault
  2150 00006448 [2E090000]              	dd	exc15
  2151 0000644C [32090000]              	dd	exc16
  2152 00006450 [36090000]              	dd	exc17
  2153 00006454 [3A090000]              	dd 	exc18
  2154 00006458 [3E090000]              	dd	exc19
  2155 0000645C [42090000]              	dd 	exc20
  2156 00006460 [46090000]              	dd	exc21
  2157 00006464 [4A090000]              	dd	exc22
  2158 00006468 [4E090000]              	dd	exc23
  2159 0000646C [52090000]              	dd 	exc24
  2160 00006470 [56090000]              	dd	exc25
  2161 00006474 [5A090000]              	dd	exc26
  2162 00006478 [5E090000]              	dd	exc27
  2163 0000647C [62090000]              	dd 	exc28
  2164 00006480 [66090000]              	dd	exc29
  2165 00006484 [6A090000]              	dd 	exc30
  2166 00006488 [6E090000]              	dd	exc31
  2167                                  	; Interrupt list
  2168 0000648C [24070000]              	dd	timer_int	; INT 20h
  2169                                  		;dd	irq0	
  2170 00006490 [240C0000]              	dd	keyb_int	; 27/08/2014
  2171                                  		;dd	irq1
  2172 00006494 [3F080000]              	dd	irq2
  2173                                  		; COM2 int
  2174 00006498 [43080000]              	dd	irq3
  2175                                  		; COM1 int
  2176 0000649C [4E080000]              	dd	irq4
  2177 000064A0 [59080000]              	dd	irq5
  2178                                  ;DISKETTE_INT: ;06/02/2015
  2179 000064A4 [CC260000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2180                                  		;dd	irq6
  2181                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2182                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2183 000064A8 [D50B0000]              	dd	default_irq7	; 25/02/2015
  2184                                  		;dd	irq7
  2185                                  ; Real Time Clock Interrupt
  2186 000064AC [780A0000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2187                                  		;dd	irq8	; INT 28h
  2188 000064B0 [69080000]              	dd	irq9
  2189 000064B4 [6D080000]              	dd	irq10
  2190 000064B8 [71080000]              	dd	irq11
  2191 000064BC [75080000]              	dd	irq12
  2192 000064C0 [79080000]              	dd	irq13
  2193                                  ;HDISK_INT1:  ;06/02/2015 	
  2194 000064C4 [F32E0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2195                                  		;dd	irq14
  2196                                  ;HDISK_INT2:  ;06/02/2015
  2197 000064C8 [162F0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2198                                  		;dd	irq15	; INT 2Fh
  2199                                  		; 14/08/2015
  2200 000064CC [873B0000]              	dd	sysent		; INT 30h (system calls)
  2201                                  	
  2202                                  	;dd	ignore_int
  2203 000064D0 00000000                	dd	0
  2204                                  
  2205                                  ;;;
  2206                                  ;;; 11/03/2015
  2207                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2208                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2209                              <1> ; Last Modification: 11/03/2015
  2210                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2211                              <1> ;
  2212                              <1> ; ///////// KEYBOARD DATA ///////////////
  2213                              <1> 
  2214                              <1> ; 05/12/2014
  2215                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2216                              <1> ; 03/06/86  KEYBOARD BIOS
  2217                              <1> 
  2218                              <1> ;---------------------------------------------------------------------------------
  2219                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2220                              <1> ;---------------------------------------------------------------------------------
  2221                              <1> 
  2222                              <1> ;-----	TABLES FOR ALT CASE ------------
  2223                              <1> ;-----	ALT-INPUT-TABLE 
  2224 000064D4 524F50514B          <1> K30:	db	82,79,80,81,75
  2225 000064D9 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2226                              <1> ;-----	SUPER-SHIFT-TABLE 
  2227 000064DE 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2228 000064E4 161718191E1F        <1> 	db	22,23,24,25,30,31
  2229 000064EA 202122232425        <1> 	db	32,33,34,35,36,37
  2230 000064F0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2231 000064F6 3132                <1> 	db	49,50
  2232                              <1> 
  2233                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2234                              <1> ;-----	KEY_TABLE 
  2235 000064F8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2236 000064F9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2237 000064FE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2238                              <1> _K6L    equ     $-_K6
  2239                              <1> 
  2240                              <1> ;-----	MASK_TABLE
  2241 00006500 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2242 00006501 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2243 00006506 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2244                              <1> 
  2245                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2246 00006508 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2247 0000650E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2248 00006514 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2249 0000651A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2250 00006520 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2251 00006526 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2252 0000652C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2253 00006532 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2254 00006538 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2255 0000653E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2256                              <1> 	;				;----- FUNCTIONS ------		
  2257 00006542 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2258 00006548 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2259 0000654E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2260 00006554 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2261 0000655A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2262                              <1> 
  2263                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2264 00006560 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2264 00006569 39302D3D0809        <1>
  2265 0000656F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2265 00006578 705B5D0DFF61736466- <1>
  2265 00006581 67686A6B6C3B27      <1>
  2266 00006588 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2266 00006591 6D2C2E2FFF2AFF20FF  <1>
  2267                              <1> ;-----	LC TABLE SCAN
  2268 0000659A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2269 0000659F 4041424344          <1> 	db	64,65,66,67,68
  2270 000065A4 FFFF                <1> 	db	-1,-1			; NL, SL
  2271                              <1> 
  2272                              <1> ;-----	KEYPAD TABLE
  2273 000065A6 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2274 000065AC 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2275 000065B3 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2276                              <1> 
  2277                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2278 000065B8 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2278 000065C1 28295F2B0800        <1>
  2279 000065C7 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2279 000065D0 507B7D0DFF41534446- <1>
  2279 000065D9 47484A4B4C3A22      <1>
  2280 000065E0 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2280 000065E9 4D3C3E3FFF2AFF20FF  <1>
  2281                              <1> ;-----	UC TABLE SCAN
  2282 000065F2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2283 000065F7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2284 000065FC FFFF                <1> 	db	-1,-1			; NL, SL
  2285                              <1> 
  2286                              <1> ;-----	NUM STATE TABLE
  2287 000065FE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2287 00006607 3233302E            <1>
  2288                              <1> 	;
  2289 0000660B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2290                              <1> 
  2291                              <1> Align	4
  2292                              <1> ;----------------------------------------
  2293                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2294                              <1> ;----------------------------------------
  2295 00006610 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2296 00006611 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2297                              <1> 				; (29h default setting for video mode 3)
  2298                              <1> 				; Mode Select register Bits
  2299                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2300                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2301                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2302                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2303                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2304                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2305                              <1> 				;   BIT 6, 7 - Not Used
  2306                              <1> 
  2307                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2308                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2309                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2310                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2311                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2312                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2313                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2314                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2315                              <1> ; Mode & 37h = Video signal OFF
  2316                              <1> 			
  2317                              <1> 
  2318                              <1> ; 26/08/2014
  2319                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2320                              <1> ; Derived from IBM "pc-at" 
  2321                              <1> ; rombios source code (06/10/1985)
  2322                              <1> ; 'dseg.inc'
  2323                              <1> 
  2324                              <1> ;---------------------------------------;
  2325                              <1> ;	SYSTEM DATA AREA		;
  2326                              <1> ;----------------------------------------
  2327 00006612 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2328                              <1> 
  2329                              <1> ;----------------------------------------
  2330                              <1> ;	KEYBOARD DATA AREAS		;
  2331                              <1> ;----------------------------------------
  2332                              <1> 
  2333 00006613 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2334 00006614 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2335 00006615 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2336 00006616 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2337 00006617 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2338 00006618 [28660000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2339 0000661C [48660000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2340 00006620 [28660000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2341 00006624 [28660000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2342                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2343 00006628 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2344                              <1> 
  2345                              <1> ; /// End Of KEYBOARD DATA ///
  2208                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2209                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2210                              <1> ; Last Modification: 11/03/2015
  2211                              <1> ;		    (Data section for 'VIDEO.INC')	
  2212                              <1> ;
  2213                              <1> ; ///////// VIDEO DATA ///////////////
  2214                              <1> 
  2215                              <1> video_params:
  2216                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2217                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2218                              <1> 	; VIDEO MODE 3
  2219 00006648 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2220 0000664F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2221 00006654 00000000            <1> 	db	0,0,0,0
  2222                              <1> 
  2223                              <1> ; /// End Of VIDEO DATA ///
  2209                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2210                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2211                              <1> ; Last Modification: 11/03/2015
  2212                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2213                              <1> ;
  2214                              <1> ; *****************************************************************************
  2215                              <1> 
  2216                              <1> ;----------------------------------------
  2217                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2218                              <1> ;	REFERENCED BY POST & BIOS	:
  2219                              <1> ;----------------------------------------
  2220                              <1> 
  2221 00006658 [BB660000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2222                              <1> 
  2223                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2224                              <1> ;----------------------------------------------------------------
  2225                              <1> ; DISK_BASE							:
  2226                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2227                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2228                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2229                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2230                              <1> ;----------------------------------------------------------------
  2231                              <1> 
  2232                              <1> ;DISK_BASE:	
  2233                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2234                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2235                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2236                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2237                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2238                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2239                              <1> ;	DB	01BH		; GAP LENGTH
  2240                              <1> ;	DB	0FFH		; DTL
  2241                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2242                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2243                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2244                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2245                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2246                              <1> 
  2247                              <1> ;----------------------------------------
  2248                              <1> ;	ROM BIOS DATA AREAS		:
  2249                              <1> ;----------------------------------------
  2250                              <1> 
  2251                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2252                              <1> 
  2253                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2254                              <1> 
  2255                              <1> ;----------------------------------------
  2256                              <1> ;	DISKETTE DATA AREAS		:
  2257                              <1> ;----------------------------------------
  2258                              <1> 
  2259                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2260                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2261                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2262                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2263                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2264                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2265                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2266                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2267                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2268                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2269                              <1> 
  2270                              <1> ;----------------------------------------
  2271                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2272                              <1> ;----------------------------------------
  2273                              <1> 
  2274                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2275                              <1> 
  2276                              <1> ;----------------------------------------
  2277                              <1> ;	TIMER DATA AREA 		:
  2278                              <1> ;----------------------------------------
  2279                              <1> 
  2280                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2281                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2282                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2283                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2284                              <1> 
  2285                              <1> ;----------------------------------------
  2286                              <1> ;	ADDITIONAL MEDIA DATA		:
  2287                              <1> ;----------------------------------------
  2288                              <1> 
  2289                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2290                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2291                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2292                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2293                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2294                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2295                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2296                              <1> 
  2297                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2298                              <1> 
  2299                              <1> ;--------------------------------------------------------
  2300                              <1> ;	DRIVE TYPE TABLE				:
  2301                              <1> ;--------------------------------------------------------
  2302                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2303                              <1> DR_TYPE:
  2304 0000665C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2305                              <1>                 ;DW      MD_TBL1
  2306 0000665D [7A660000]          <1> 		dd	MD_TBL1
  2307 00006661 82                  <1> 		DB	02+BIT7ON
  2308                              <1> 		;DW      MD_TBL2
  2309 00006662 [87660000]          <1>                 dd      MD_TBL2
  2310 00006666 02                  <1> DR_DEFAULT:	DB	02
  2311                              <1>                 ;DW      MD_TBL3
  2312 00006667 [94660000]          <1> 		dd      MD_TBL3
  2313 0000666B 03                  <1> 		DB	03
  2314                              <1>                 ;DW      MD_TBL4
  2315 0000666C [A1660000]          <1> 		dd      MD_TBL4
  2316 00006670 84                  <1> 		DB	04+BIT7ON
  2317                              <1>                 ;DW      MD_TBL5
  2318 00006671 [AE660000]          <1> 		dd      MD_TBL5
  2319 00006675 04                  <1> 		DB	04
  2320                              <1>                 ;DW      MD_TBL6
  2321 00006676 [BB660000]          <1> 		dd      MD_TBL6
  2322                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2323                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2324                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2325                              <1> ;--------------------------------------------------------
  2326                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2327                              <1> ;--------------------------------------------------------
  2328                              <1> ;--------------------------------------------------------
  2329                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2330                              <1> ;--------------------------------------------------------
  2331                              <1> MD_TBL1:        
  2332 0000667A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2333 0000667B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2334 0000667C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2335 0000667D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2336 0000667E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2337 0000667F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2338 00006680 FF                  <1> 	DB	0FFH		; DTL
  2339 00006681 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2340 00006682 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2341 00006683 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2342 00006684 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2343 00006685 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2344 00006686 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2345                              <1> ;--------------------------------------------------------
  2346                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2347                              <1> ;--------------------------------------------------------
  2348                              <1> MD_TBL2:        
  2349 00006687 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2350 00006688 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2351 00006689 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2352 0000668A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2353 0000668B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2354 0000668C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2355 0000668D FF                  <1> 	DB	0FFH		; DTL
  2356 0000668E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2357 0000668F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2358 00006690 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2359 00006691 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2360 00006692 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2361 00006693 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2362                              <1> ;--------------------------------------------------------
  2363                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2364                              <1> ;--------------------------------------------------------
  2365                              <1> MD_TBL3:
  2366 00006694 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2367 00006695 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2368 00006696 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2369 00006697 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2370 00006698 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2371 00006699 1B                  <1> 	DB	01BH		; GAP LENGTH
  2372 0000669A FF                  <1> 	DB	0FFH		; DTL
  2373 0000669B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2374 0000669C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2375 0000669D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2376 0000669E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2377 0000669F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2378 000066A0 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2379                              <1> ;--------------------------------------------------------
  2380                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2381                              <1> ;--------------------------------------------------------
  2382                              <1> MD_TBL4:
  2383 000066A1 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2384 000066A2 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2385 000066A3 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2386 000066A4 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2387 000066A5 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2388 000066A6 2A                  <1> 	DB	02AH		; GAP LENGTH
  2389 000066A7 FF                  <1> 	DB	0FFH		; DTL
  2390 000066A8 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2391 000066A9 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2392 000066AA 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2393 000066AB 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2394 000066AC 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2395 000066AD 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2396                              <1> ;--------------------------------------------------------
  2397                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2398                              <1> ;--------------------------------------------------------
  2399                              <1> MD_TBL5:
  2400 000066AE DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2401 000066AF 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2402 000066B0 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2403 000066B1 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2404 000066B2 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2405 000066B3 2A                  <1> 	DB	02AH		; GAP LENGTH
  2406 000066B4 FF                  <1> 	DB	0FFH		; DTL
  2407 000066B5 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2408 000066B6 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2409 000066B7 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2410 000066B8 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2411 000066B9 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2412 000066BA 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2413                              <1> ;--------------------------------------------------------
  2414                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2415                              <1> ;--------------------------------------------------------
  2416                              <1> MD_TBL6:
  2417 000066BB AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2418 000066BC 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2419 000066BD 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2420 000066BE 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2421 000066BF 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2422 000066C0 1B                  <1> 	DB	01BH		; GAP LENGTH
  2423 000066C1 FF                  <1> 	DB	0FFH		; DTL
  2424 000066C2 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2425 000066C3 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2426 000066C4 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2427 000066C5 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2428 000066C6 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2429 000066C7 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2430                              <1> 
  2431                              <1> 
  2432                              <1> ; << diskette.inc >>
  2433                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2434                              <1> ;
  2435                              <1> ;----------------------------------------
  2436                              <1> ;	ROM BIOS DATA AREAS		:
  2437                              <1> ;----------------------------------------
  2438                              <1> 
  2439                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2440                              <1> 
  2441                              <1> ;----------------------------------------
  2442                              <1> ;	FIXED DISK DATA AREAS		:
  2443                              <1> ;----------------------------------------
  2444                              <1> 
  2445                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2446                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2447                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2448                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2449                              <1> 
  2450                              <1> ;----------------------------------------
  2451                              <1> ;	ADDITIONAL MEDIA DATA		:
  2452                              <1> ;----------------------------------------
  2453                              <1> 
  2454                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2455                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2456                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2457                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2458                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2459                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2460                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2461                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2462                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2463                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2464                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2465                              <1> 
  2466                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2467                              <1> ;
  2468                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2469                              <1> 
  2470                              <1> ERR_TBL:
  2471 000066C8 E0                  <1> 	db	NO_ERR
  2472 000066C9 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2473 000066CD 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2474                              <1> 
  2475                              <1> ; 17/12/2014 (mov ax, [cfd])
  2476                              <1> ; 11/12/2014
  2477 000066D1 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2478                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2479 000066D2 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2480                              <1> 					; (initial value of 'pfd 
  2481                              <1> 					; must be different then 'cfd' value
  2482                              <1> 					; to force updating/initializing
  2483                              <1> 					; current drive parameters) 
  2484 000066D3 90                  <1> align 2
  2485                              <1> 
  2486 000066D4 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2487                              <1> 			      ; (170h)
  2488 000066D6 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2489                              <1> 
  2490                              <1> ; 05/01/2015 
  2491 000066D8 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2492                              <1> 
  2493                              <1> ; *****************************************************************************
  2210                                  ;;;
  2211                                  
  2212 000066D9 90                      Align 2
  2213                                  
  2214                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2215 000066DA 00                      boot_drv:    db 0 ; boot drive number (physical)
  2216                                  ; 24/11/2014
  2217 000066DB 00                      drv:	     db 0 
  2218 000066DC 00                      last_drv:    db 0 ; last hdd
  2219 000066DD 00                      hdc:         db 0  ; number of hard disk drives
  2220                                  		     ; (present/detected)
  2221                                  ;
  2222                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2223                                  ; Physical drive type & flags
  2224 000066DE 00                      fd0_type:    db 0  ; floppy drive type
  2225 000066DF 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2226                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2227                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2228                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2229                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2230 000066E0 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2231 000066E1 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2232 000066E2 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2233 000066E3 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2234                                  		     ; bit 0 - Fixed disk access subset supported
  2235                                  		     ; bit 1 - Drive locking and ejecting
  2236                                  		     ; bit 2 - Enhanced disk drive support
  2237                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2238                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2239                                  		     ; will interpret it as 'LBA ready'!)		
  2240                                  
  2241                                  ; 11/03/2015 - 10/07/2015
  2242 000066E4 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2242 000066ED 0000000000         
  2243 000066F2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2243 000066FB 0000000000         
  2244 00006700 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2244 00006709 0000000000         
  2245 0000670E 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2245 00006717 000000000000000000-
  2245 00006720 000000000000000000-
  2245 00006729 00                 
  2246 0000672A 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2247 00006731 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2248                                  ;
  2249                                  
  2250                                  ; 27/08/2014
  2251                                  scr_row:
  2252 00006738 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2253                                  scr_col:
  2254 0000673C 00000000                	dd 0
  2255                                  
  2256                                  ;; 14/08/2015
  2257                                  ;;msgPM:
  2258                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2259                                  msgKVER:
  2260 00006740 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.1 [31/12/2021]", 0
  2260 00006749 58203338362076312E-
  2260 00006752 31202D204B65726E65-
  2260 0000675B 6C2076302E322E312E-
  2260 00006764 31205B33312F31322F-
  2260 0000676D 323032315D00       
  2261                                  
  2262 00006773 90                      Align 2
  2263                                  
  2264                                  ; 20/08/2014
  2265                                    ; /* This is the default interrupt "handler" :-) */ 
  2266                                    ; Linux v0.12 (head.s)
  2267                                  int_msg:
  2268 00006774 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2268 0000677D 6E7465727275707420-
  2268 00006786 212000             
  2269                                  
  2270 00006789 90                      Align 2  
  2271                                  
  2272                                  ; 21/08/2014
  2273                                  timer_msg:
  2274 0000678A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2274 00006793 542032306829202120-
  2274 0000679C 54696D657220496E74-
  2274 000067A5 657272757074203A20 
  2275                                  tcountstr:
  2276 000067AE 303030303020            	db "00000 "
  2277 000067B4 00                      	db 0
  2278                                  
  2279 000067B5 90                      Align 2
  2280                                  	; 21/08/2014
  2281                                  exc_msg:
  2282 000067B6 435055206578636570-     	db "CPU exception ! "
  2282 000067BF 74696F6E202120     
  2283                                  excnstr: 		; 25/08/2014
  2284 000067C6 3F3F68202045495020-     	db "??h", "  EIP : "
  2284 000067CF 3A20               
  2285                                  EIPstr: ; 29/08/2014
  2286 000067D1 00<rep Ch>              	times 12 db 0
  2287                                  rtc_msg:
  2288 000067DD 5265616C2054696D65-     	db "Real Time Clock - "
  2288 000067E6 20436C6F636B202D20 
  2289                                  datestr:
  2290 000067EF 30302F30302F303030-     	db "00/00/0000"
  2290 000067F8 30                 
  2291 000067F9 20                      	db " "
  2292                                  daystr:
  2293 000067FA 44415920                	db "DAY "
  2294                                  timestr:	
  2295 000067FE 30303A30303A3030                db "00:00:00"
  2296 00006806 20                      	db " "
  2297 00006807 00                      	db 0 
  2298                                  
  2299                                  daytmp:
  2300                                  	; 28/02/2015
  2301 00006808 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2301 00006811 4F4E20545545205745-
  2301 0000681A 442054485520465249-
  2301 00006823 2053415420         
  2302                                  
  2303 00006828 FF                      ptime_seconds: db 0FFh
  2304                                  
  2305                                  	; 23/02/2015
  2306                                  	; 25/08/2014
  2307                                  ;scounter:
  2308                                  ;	db 5
  2309                                  ;	db 19
  2310                                  
  2311                                  ; 05/11/2014
  2312                                  msg_out_of_memory:
  2313 00006829 070D0A                  	db 	07h, 0Dh, 0Ah
  2314 0000682C 496E73756666696369-             db      'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2314 00006835 656E74206D656D6F72-
  2314 0000683E 79202120284D696E69-
  2314 00006847 6D756D2032204D4220-
  2314 00006850 6D656D6F7279206973-
  2314 00006859 206E65656465642E29 
  2315 00006862 0D0A00                   	db	0Dh, 0Ah, 0
  2316                                  	;
  2317                                  setup_error_msg:
  2318 00006865 0D0A                    	db 0Dh, 0Ah
  2319 00006867 4469736B2053657475-     	db 'Disk Setup Error!' 
  2319 00006870 70204572726F7221   
  2320 00006878 0D0A00                  	db 0Dh, 0Ah,0
  2321                                  
  2322                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2323                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2324                                  ;	  db 0 ; upper left row (for scroll)	
  2325                                  
  2326                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2327                                  ;	  db 24 ; lower right row (for scroll)
  2328                                  
  2329                                  
  2330                                  ; 06/11/2014 (Temporary Data)
  2331                                  ; Memory Information message
  2332                                  ; 14/08/2015
  2333                                  msg_memory_info:
  2334 0000687B 07                      	db	07h
  2335 0000687C 0D0A                    	db	0Dh, 0Ah
  2336                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2337 0000687E 546F74616C206D656D-     	db	"Total memory : "
  2337 00006887 6F7279203A20       
  2338                                  mem_total_b_str: ; 10 digits
  2339 0000688D 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2339 00006896 302062797465730D0A 
  2340 0000689F 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2340 000068A8 202020202020202020 
  2341                                  mem_total_p_str: ; 7 digits
  2342 000068B1 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2342 000068BA 616765730D0A       
  2343 000068C0 0D0A                    	db 	0Dh, 0Ah
  2344 000068C2 46726565206D656D6F-     	db	"Free memory  : "
  2344 000068CB 727920203A20       
  2345                                  free_mem_b_str:  ; 10 digits
  2346 000068D1 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2346 000068DA 3F2062797465730D0A 
  2347 000068E3 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2347 000068EC 202020202020202020 
  2348                                  free_mem_p_str:  ; 7 digits
  2349 000068F5 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2349 000068FE 616765730D0A       
  2350 00006904 0D0A00                  	db	0Dh, 0Ah, 0
  2351                                  
  2352                                  dsk_ready_msg:
  2353 00006907 0D0A                    	db 	0Dh, 0Ah
  2354                                  dsktype:
  2355 00006909 6664                    	db	'fd'
  2356                                  dskx:
  2357 0000690B 30                      	db	'0'
  2358 0000690C 20                      	db	20h
  2359 0000690D 697320524541445920-     	db 	'is READY ...'
  2359 00006916 2E2E2E             
  2360 00006919 00                      	db 	0
  2361                                  nextline:
  2362 0000691A 0D0A00                  	db 	0Dh, 0Ah, 0
  2363                                  
  2364                                  ; KERNEL - SYSINIT Messages
  2365                                  ; 24/08/2015
  2366                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2367                                  ; 14/07/2013
  2368                                  ;kernel_init_err_msg:
  2369                                  ;	db 0Dh, 0Ah
  2370                                  ;	db 07h
  2371                                  ;	db 'Kernel initialization ERROR !'
  2372                                  ;	db 0Dh, 0Ah, 0 
  2373                                  ; 24/08/2015
  2374                                  ;;; (temporary kernel init message has been removed
  2375                                  ;;;  from 'sys_init' code)
  2376                                  ;kernel_init_ok_msg: 
  2377                                  ;	db 0Dh, 0Ah
  2378                                  ;	db 07h
  2379                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2380                                  ;	db 0Dh, 0Ah
  2381                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2382                                  ;	db 0Dh, 0Ah, 0
  2383                                  panic_msg:
  2384 0000691D 0D0A07                  	db 0Dh, 0Ah, 07h
  2385 00006920 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2385 00006929 726E656C2050616E69-
  2385 00006932 632021             
  2386 00006935 0D0A00                  	db 0Dh, 0Ah, 0
  2387                                  etc_init_err_msg:
  2388 00006938 0D0A                    	db 0Dh, 0Ah
  2389 0000693A 07                      	db 07h
  2390 0000693B 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2390 00006944 74632F696E69742021-
  2390 0000694D 3F                 
  2391 0000694E 0D0A00                  	db 0Dh, 0Ah, 0
  2392                                  
  2393                                  ; 10/05/2015
  2394                                  badsys_msg:
  2395 00006951 0D0A                    	db 0Dh, 0Ah
  2396 00006953 07                      	db 07h
  2397 00006954 496E76616C69642053-     	db 'Invalid System Call !'
  2397 0000695D 797374656D2043616C-
  2397 00006966 6C2021             
  2398 00006969 0D0A                    	db 0Dh, 0Ah
  2399 0000696B 4541583A20              	db 'EAX: '
  2400                                  bsys_msg_eax:
  2401 00006970 303030303030303068      	db '00000000h'
  2402 00006979 0D0A                    	db 0Dh, 0Ah
  2403 0000697B 4549503A20              	db 'EIP: '
  2404                                  bsys_msg_eip:
  2405 00006980 303030303030303068      	db '00000000h' 
  2406 00006989 0D0A00                  	db 0Dh, 0Ah, 0
  2407                                  
  2408                                  BSYS_M_SIZE equ $ - badsys_msg
  2409                                  
  2410                                  
  2411                                  align 2
  2412                                  
  2413                                  ; EPOCH Variables
  2414                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2415                                  ; 09/04/2013 epoch variables
  2416                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2417                                  ;
  2418 0000698C B207                    year: 	dw 1970
  2419 0000698E 0100                    month: 	dw 1
  2420 00006990 0100                    day: 	dw 1
  2421 00006992 0000                    hour: 	dw 0
  2422 00006994 0000                    minute: dw 0
  2423 00006996 0000                    second: dw 0
  2424                                  
  2425                                  DMonth:
  2426 00006998 0000                    	dw 0
  2427 0000699A 1F00                    	dw 31
  2428 0000699C 3B00                    	dw 59
  2429 0000699E 5A00                    	dw 90
  2430 000069A0 7800                    	dw 120
  2431 000069A2 9700                    	dw 151
  2432 000069A4 B500                    	dw 181
  2433 000069A6 D400                    	dw 212
  2434 000069A8 F300                    	dw 243
  2435 000069AA 1101                    	dw 273
  2436 000069AC 3001                    	dw 304
  2437 000069AE 4E01                    	dw 334
  2438                                  
  2439                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2440 000069B0 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2441                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2442 000069B2 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2443                                  		   ;   between 16 MB and 4 GB.
  2444 000069B4 90<rep Ch>              align 16
  2445                                  
  2446                                  bss_start:
  2447                                  
  2448                                  ABSOLUTE bss_start
  2449                                  
  2450                                  	; 11/03/2015
  2451                                  	; Interrupt Descriptor Table (20/08/2014)
  2452                                  idt:
  2453 000069C0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2454                                  idt_end:
  2455                                  
  2456                                  ;alignb 4
  2457                                  
  2458                                  task_state_segment:
  2459                                  	; 24/03/2015
  2460 00006BC0 ????                    tss.link:   resw 1
  2461 00006BC2 ????                    	    resw 1
  2462                                  ; tss offset 4	
  2463 00006BC4 ????????                tss.esp0:   resd 1
  2464 00006BC8 ????                    tss.ss0:    resw 1
  2465 00006BCA ????                    	    resw 1	
  2466 00006BCC ????????                tss.esp1:   resd 1
  2467 00006BD0 ????                    tss.ss1:    resw 1
  2468 00006BD2 ????                    	    resw 1 	
  2469 00006BD4 ????????                tss.esp2:   resd 1
  2470 00006BD8 ????                    tss.ss2:    resw 1
  2471 00006BDA ????                    	    resw 1
  2472                                  ; tss offset 28
  2473 00006BDC ????????                tss.CR3:    resd 1
  2474 00006BE0 ????????                tss.eip:    resd 1
  2475 00006BE4 ????????                tss.eflags: resd 1
  2476                                  ; tss offset 40
  2477 00006BE8 ????????                tss.eax:    resd 1		 		
  2478 00006BEC ????????                tss.ecx:    resd 1
  2479 00006BF0 ????????                tss.edx:    resd 1
  2480 00006BF4 ????????                tss.ebx:    resd 1
  2481 00006BF8 ????????                tss.esp:    resd 1
  2482 00006BFC ????????                tss.ebp:    resd 1
  2483 00006C00 ????????                tss.esi:    resd 1
  2484 00006C04 ????????                tss.edi:    resd 1
  2485                                  ; tss offset 72
  2486 00006C08 ????                    tss.ES:     resw 1
  2487 00006C0A ????                    	    resw 1	
  2488 00006C0C ????                    tss.CS:	    resw 1
  2489 00006C0E ????                    	    resw 1
  2490 00006C10 ????                    tss.SS:	    resw 1
  2491 00006C12 ????                    	    resw 1
  2492 00006C14 ????                    tss.DS:	    resw 1
  2493 00006C16 ????                    	    resw 1
  2494 00006C18 ????                    tss.FS:	    resw 1
  2495 00006C1A ????                    	    resw 1
  2496 00006C1C ????                    tss.GS:	    resw 1
  2497 00006C1E ????                    	    resw 1		
  2498 00006C20 ????                    tss.LDTR:   resw 1
  2499 00006C22 ????                    	    resw 1
  2500                                  ; tss offset 100		
  2501 00006C24 ????                    	    resw 1		
  2502 00006C26 ????                    tss.IOPB:   resw 1
  2503                                  ; tss offset 104 
  2504                                  tss_end:
  2505                                  
  2506 00006C28 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2507                                  		  ;   (Physical address = Virtual address)	 	
  2508 00006C2C ????????                memory_size: resd 1 ; memory size in pages
  2509 00006C30 ????????                free_pages:  resd 1 ; number of free pages		
  2510 00006C34 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2511                                  		  ;   first free page search
  2512 00006C38 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2513                                  		  ;   next free page search will be
  2514                                  		  ; stopped after it. (end of M.A.T.)
  2515 00006C3C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2516                                  		  ; first free page search
  2517                                  		  ;   will be started on it. (for user)
  2518 00006C40 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2519                                  
  2520                                  ;;;
  2521                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2522                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2523 00006C44 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2524                                  			  ; NOTE: active page only
  2525 00006C46 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2526                                  active_page: 
  2527 00006C56 ??                      ptty: 	     resb 1 	  ; current tty
  2528                                  ; 01/07/2015
  2529 00006C57 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2530                                  ; 26/10/2015
  2531                                  ; 07/09/2014
  2532 00006C58 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2533                                  
  2534                                  ; 21/08/2014
  2535 00006C6C ????????                tcount:	     resd 1
  2536                                  
  2537                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2538 00006C70 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2539                                  
  2540                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2541                                  ; (open mode locks for pseudo TTYs)
  2542                                  ; [ major tty locks (return error in any conflicts) ]
  2543 00006C74 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2544                                  
  2545                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2546                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2547 00006C88 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2548                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2549                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2550                                  ;; 0 means serial port is not available 
  2551                                  ;;comprm: ; 25/06/2014
  2552 00006C92 ??                      com1p:       resb 1  ;;0E3h
  2553 00006C93 ??                      com2p:       resb 1  ;;0E3h
  2554                                  
  2555                                  ; 17/11/2015
  2556                                  ; request for response (from the terminal)	
  2557 00006C94 ????                    req_resp:     resw 1 			
  2558                                  ; 07/11/2015
  2559 00006C96 ??                      ccomport:    resb 1 ; current COM (serial) port
  2560                                  		    ; (0= COM1, 1= COM2)
  2561                                  ; 09/11/2015
  2562 00006C97 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2563                                  ; 07/11/2015
  2564 00006C98 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2565 00006C9A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2566                                  
  2567                                  ; 23/10/2015
  2568                                  ; SERIAL PORTS - COMMUNICATION MODES
  2569                                  ; (Retro UNIX 386 v1 feature only!)
  2570                                  ; 0 - command mode (default/initial mode)
  2571                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2572                                  ;;; communication modes for futre versions:  
  2573                                  ; // 2 - keyboard mode (ascii+scancode input)
  2574                                  ; // 3 - mouse mode
  2575                                  ; // 4 - device control (output) mode
  2576                                  ; VALID COMMANDS for current version:
  2577                                  ; 	'LOGIN'
  2578                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2579                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2580                                  ;  Login response: db 0FFh, 'login', 0
  2581                                  ;	 ("login request accepted, wait for login prompt") 
  2582                                  ; When a login requests is received and acknowledged (by
  2583                                  ; serial port interrupt handler (communication procedure),
  2584                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2585                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2586                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2587                                  ; 
  2588                                  ; 'sys connect' system call is used to change communication mode
  2589                                  ; except 'LOGIN' command which is used to start terminal mode
  2590                                  ; by using (COM port) terminal.
  2591                                  
  2592                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2593                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2594                                  ;com1mode:    resb 1 ; communication mode for COM1
  2595                                  ;com1com:     resb 1 ; communication command for COM1
  2596                                  ;com2mode:    resb 1 ; communication mode for COM1
  2597                                  ;com2com      resb 1 ; communication command for COM1
  2598                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2599                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2600                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2601                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2602                                  
  2603                                  ; 22/08/2014 (RTC)
  2604                                  ; (Packed BCD)
  2605 00006C9C ??                      time_seconds: resb 1
  2606 00006C9D ??                      time_minutes: resb 1
  2607 00006C9E ??                      time_hours:   resb 1
  2608 00006C9F ??                      date_wday:    resb 1
  2609 00006CA0 ??                      date_day:     resb 1
  2610 00006CA1 ??                      date_month:   resb 1			
  2611 00006CA2 ??                      date_year:    resb 1
  2612 00006CA3 ??                      date_century: resb 1
  2613                                  
  2614                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2615                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2616                              <1> ; Last Modification: 10/07/2015
  2617                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2618                              <1> ;
  2619                              <1> ; *****************************************************************************
  2620                              <1> 
  2621                              <1> alignb 2
  2622                              <1> 
  2623                              <1> ;----------------------------------------
  2624                              <1> ;	TIMER DATA AREA 		:
  2625                              <1> ;----------------------------------------
  2626                              <1> 
  2627                              <1> TIMER_LH:	; 16/02/205
  2628 00006CA4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2629 00006CA6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2630 00006CA8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2631                              <1> 
  2632                              <1> ;----------------------------------------
  2633                              <1> ;	DISKETTE DATA AREAS		:
  2634                              <1> ;----------------------------------------
  2635                              <1> 
  2636 00006CA9 ??                  <1> SEEK_STATUS:	resb	1
  2637 00006CAA ??                  <1> MOTOR_STATUS:	resb	1
  2638 00006CAB ??                  <1> MOTOR_COUNT:	resb	1
  2639 00006CAC ??                  <1> DSKETTE_STATUS:	resb	1
  2640 00006CAD ??????????????      <1> NEC_STATUS:	resb	7
  2641                              <1> 
  2642                              <1> ;----------------------------------------
  2643                              <1> ;	ADDITIONAL MEDIA DATA		:
  2644                              <1> ;----------------------------------------
  2645                              <1> 
  2646 00006CB4 ??                  <1> LASTRATE:	resb 	1
  2647 00006CB5 ??                  <1> HF_STATUS:	resb 	1
  2648 00006CB6 ??                  <1> HF_ERROR:	resb 	1
  2649 00006CB7 ??                  <1> HF_INT_FLAG:	resb 	1
  2650 00006CB8 ??                  <1> HF_CNTRL:	resb 	1
  2651 00006CB9 ????????            <1> DSK_STATE:	resb 	4
  2652 00006CBD ????                <1> DSK_TRK:	resb 	2
  2653                              <1> 
  2654                              <1> ;----------------------------------------
  2655                              <1> ;	FIXED DISK DATA AREAS		:
  2656                              <1> ;----------------------------------------
  2657                              <1> 
  2658 00006CBF ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2659 00006CC0 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2660 00006CC1 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2661                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2662                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2663                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2664                              <1> 
  2665 00006CC2 ????                <1> alignb 4
  2666                              <1> 
  2667                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2668                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2669                              <1> HF_TBL_VEC: ; 22/12/2014	
  2670 00006CC4 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2671 00006CC8 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2672 00006CCC ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2673 00006CD0 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2674                              <1> 
  2675                              <1> ; 03/01/2015
  2676 00006CD4 ??                  <1> LBAMode:     	resb	1
  2677                              <1> 
  2678                              <1> ; *****************************************************************************
  2615                                  
  2616                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2617                                  
  2618                                  ;alignb 2
  2619                                  
  2620                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2621                              <1> ; Retro UNIX 386 v1 Kernel - ux.s
  2622                              <1> ; Last Modification: 04/12/2015
  2623                              <1> ;
  2624                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2625                              <1> ; (Modified from 
  2626                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2627                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2628                              <1> ; ----------------------------------------------------------------------------
  2629                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2630                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2631                              <1> ; <Bell Laboratories (17/3/1972)>
  2632                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2633                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2634                              <1> ; ****************************************************************************
  2635                              <1> 
  2636 00006CD5 ??                  <1> alignb 2
  2637                              <1> 
  2638                              <1> inode:
  2639                              <1> 	; 11/03/2013. 
  2640                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2641                              <1> 	;i.
  2642                              <1> 
  2643 00006CD6 ????                <1> 	i.flgs:	 resw 1
  2644 00006CD8 ??                  <1> 	i.nlks:	 resb 1
  2645 00006CD9 ??                  <1> 	i.uid:	 resb 1
  2646 00006CDA ????                <1>         i.size:  resw 1 ; size
  2647 00006CDC <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2648 00006CEC ????????            <1> 	i.ctim:	 resd 1
  2649 00006CF0 ????????            <1> 	i.mtim:	 resd 1
  2650 00006CF4 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2651                              <1> 
  2652                              <1> I_SIZE	equ $ - inode 
  2653                              <1> 
  2654                              <1> process:
  2655                              <1> 	; 06/05/2015
  2656                              <1> 	; 11/03/2013 - 05/02/2014
  2657                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2658                              <1> 	;p.
  2659                              <1> 	
  2660 00006CF6 <res 20h>           <1>         p.pid:   resw nproc
  2661 00006D16 <res 20h>           <1>         p.ppid:  resw nproc
  2662 00006D36 <res 20h>           <1>         p.break: resw nproc
  2663 00006D56 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2664 00006D66 <res 10h>           <1> 	p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2665 00006D76 <res 10h>           <1> 	p.link:	 resb nproc
  2666 00006D86 <res 10h>           <1> 	p.stat:	 resb nproc
  2667                              <1> 
  2668                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2669 00006D96 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2670                              <1> 			    ; 'user' structure	
  2671                              <1> 
  2672                              <1> P_SIZE	equ $ - process
  2673                              <1> 
  2674                              <1> ; fsp table (original UNIX v1)
  2675                              <1> ;
  2676                              <1> ;Entry
  2677                              <1> ;          15                                      0
  2678                              <1> ;  1     |---|---------------------------------------|
  2679                              <1> ;        |r/w|       i-number of open file           |
  2680                              <1> ;        |---|---------------------------------------| 
  2681                              <1> ;        |               device number               |
  2682                              <1> ;        |-------------------------------------------|
  2683                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2684                              <1> ;        |-------------------------------------------| 
  2685                              <1> ;        |  flag that says    | number of processes  |
  2686                              <1> ;        |   file deleted     | that have file open  |
  2687                              <1> ;        |-------------------------------------------| 
  2688                              <1> ;  2     |                                           |
  2689                              <1> ;        |-------------------------------------------| 
  2690                              <1> ;        |                                           |
  2691                              <1> ;        |-------------------------------------------|
  2692                              <1> ;        |                                           |
  2693                              <1> ;        |-------------------------------------------|
  2694                              <1> ;        |                                           |
  2695                              <1> ;        |-------------------------------------------| 
  2696                              <1> ;  3     |                                           | 
  2697                              <1> ;        |                                           |  
  2698                              <1> ;
  2699                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2700                              <1> 
  2701                              <1> ; 15/04/2015
  2702 00006DD6 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2703 00006FCA <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2704 00006FEA ????                <1> ii:	 resw 1
  2705 00006FEC ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2706 00006FEE ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2707                              <1> ; 18/05/2015
  2708                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2709                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2710                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2711                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2712                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2713                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2714                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2715                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2716                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2717                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2718                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2719 00006FF0 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2720                              <1> 	        ; as above, for physical drives numbers in following table
  2721 00006FF1 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2722                              <1> ; 15/04/2015
  2723 00006FF2 ??                  <1> active:	 resb 1 
  2724 00006FF3 ??                  <1> 	 resb 1 ; 09/06/2015
  2725 00006FF4 ????                <1> mnti:	 resw 1
  2726 00006FF6 ????                <1> mpid:	 resw 1
  2727 00006FF8 ????                <1> rootdir: resw 1
  2728                              <1> ; 14/02/2014
  2729                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2730                              <1> ;		      Single level run queue
  2731                              <1> ;		      (in order to solve sleep/wakeup lock)
  2732 00006FFA ????                <1> runq:	 resw 1
  2733 00006FFC ??                  <1> imod:	 resb 1
  2734 00006FFD ??                  <1> smod:	 resb 1
  2735 00006FFE ??                  <1> mmod:	 resb 1
  2736 00006FFF ??                  <1> sysflg:	 resb 1
  2737                              <1> 
  2738                              <1> alignb 4
  2739                              <1> 
  2740                              <1> user:
  2741                              <1> 	; 04/12/2015 
  2742                              <1> 	; 18/10/2015
  2743                              <1> 	; 12/10/2015
  2744                              <1> 	; 21/09/2015
  2745                              <1> 	; 24/07/2015
  2746                              <1> 	; 16/06/2015
  2747                              <1> 	; 09/06/2015
  2748                              <1> 	; 11/05/2015
  2749                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2750                              <1> 	; 10/10/2013
  2751                              <1> 	; 11/03/2013. 
  2752                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2753                              <1> 	;u.
  2754                              <1> 
  2755 00007000 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2756 00007004 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2757 00007008 ????????            <1> 	u.r0:	  resd 1 ; eax
  2758 0000700C ????                <1> 	u.cdir:	  resw 1
  2759 0000700E <res Ah>            <1> 	u.fp:	  resb 10
  2760 00007018 ????????            <1> 	u.fofp:	  resd 1
  2761 0000701C ????????            <1> 	u.dirp:	  resd 1
  2762 00007020 ????????            <1> 	u.namep:  resd 1
  2763 00007024 ????????            <1> 	u.off:	  resd 1
  2764 00007028 ????????            <1> 	u.base:	  resd 1
  2765 0000702C ????????            <1> 	u.count:  resd 1
  2766 00007030 ????????            <1> 	u.nread:  resd 1
  2767 00007034 ????????            <1> 	u.break:  resd 1 ; break
  2768 00007038 ????                <1> 	u.ttyp:	  resw 1 
  2769 0000703A <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2770                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2771 0000704A ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2772 0000704B ??                  <1> 	u.pri:	  resb 1 ; 
  2773 0000704C ????                <1> 	u.intr:	  resw 1
  2774 0000704E ????                <1> 	u.quit:	  resw 1
  2775                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2776 00007050 ????                <1> 	u.ilgins: resw 1
  2777 00007052 ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2778 00007054 ??                  <1> 	u.uid:	  resb 1 ; uid
  2779 00007055 ??                  <1> 	u.ruid:	  resb 1
  2780 00007056 ??                  <1> 	u.bsys:	  resb 1
  2781 00007057 ??                  <1> 	u.uno:	  resb 1
  2782 00007058 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2783                              <1> 	; tty number (rtty, rcvt, wtty)
  2784 0000705C ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2785                              <1> 	; last error number
  2786 0000705D ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2787                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2788 00007061 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2789 00007065 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2790 00007069 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2791 0000706D ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2792                              <1> 	;u.pncount: resw 1 
  2793                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2794                              <1> 	;u.pnbase:  resd 1 
  2795                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2796                              <1> 			 ; 09/06/2015
  2797 0000706F ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2798 00007070 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2799                              <1> 			 ; 24/07/2015 - 24/06/2015
  2800                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2801                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2802                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2803                              <1>  			 ; 24/06/2015	  	
  2804                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2805                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2806                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2807 00007071 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2808                              <1> 
  2809 00007075 ??????              <1> alignb 4
  2810                              <1> 
  2811                              <1> U_SIZE	equ $ - user
  2812                              <1> 
  2813                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2814 00007078 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2815 0000707C ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2816 00007080 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2817 00007084 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2818 00007086 ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2819 00007088 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2820                              <1> 
  2821                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2822                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2823 0000708C ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2824 0000708D ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2825 0000708E ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2826 0000708F ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2827                              <1> 
  2828                              <1> ;alignb 4
  2829                              <1> 
  2830                              <1> ; 22/08/2015
  2831 00007090 <res C30h>          <1> buffer: resb nbuf * 520
  2832                              <1> 
  2833 00007CC0 ????????????????    <1> sb0:	resd 2
  2834                              <1> ;s:
  2835                              <1> ; (root disk) super block buffer
  2836                              <1> systm:
  2837                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2838                              <1> 	; 11/03/2013. 
  2839                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2840                              <1> 	;s.
  2841                              <1> 
  2842 00007CC8 ????                <1> 	resw 1
  2843 00007CCA <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2844 00007E32 ????                <1> 	resw 1
  2845 00007E34 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2846 00007E54 ????????            <1> 	s.time:	 resd 1
  2847 00007E58 ????????            <1> 	s.syst:	 resd 1
  2848 00007E5C ????????            <1>         s.wait_: resd 1 ; wait
  2849 00007E60 ????????            <1> 	s.idlet: resd 1
  2850 00007E64 ????????            <1> 	s.chrgt: resd 1
  2851 00007E68 ????                <1> 	s.drerr: resw 1
  2852                              <1> 
  2853                              <1> S_SIZE	equ $ - systm
  2854                              <1> 
  2855 00007E6A <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2856                              <1> 
  2857 00007EC8 ????????????????    <1> sb1:	resd 2
  2858                              <1> ; (mounted disk) super block buffer
  2859                              <1> mount:	
  2860 00007ED0 <res 200h>          <1> 	resb 512  ; 03/06/2015
  2861                              <1> 
  2862                              <1> ;/ ux -- unix
  2863                              <1> ;
  2864                              <1> ;systm:
  2865                              <1> ;
  2866                              <1> ;	.=.+2
  2867                              <1> ;	.=.+128.
  2868                              <1> ;	.=.+2
  2869                              <1> ;	.=.+64.
  2870                              <1> ;	s.time: .=.+4
  2871                              <1> ;	s.syst: .=.+4
  2872                              <1> ;	s.wait: .=.+4
  2873                              <1> ;	s.idlet:.=.+4
  2874                              <1> ;	s.chrgt:.=.+4
  2875                              <1> ;	s.drerr:.=.+2
  2876                              <1> ;inode:
  2877                              <1> ;	i.flgs: .=.+2
  2878                              <1> ;	i.nlks: .=.+1
  2879                              <1> ;	i.uid:  .=.+1
  2880                              <1> ;	i.size: .=.+2
  2881                              <1> ;	i.dskp: .=.+16.
  2882                              <1> ;	i.ctim: .=.+4
  2883                              <1> ;	i.mtim: .=.+4
  2884                              <1> ;	. = inode+32.
  2885                              <1> ;mount:	.=.+1024.
  2886                              <1> ;proc:
  2887                              <1> ;	p.pid:  .=.+[2*nproc]
  2888                              <1> ;	p.dska: .=.+[2*nproc]
  2889                              <1> ;	p.ppid: .=.+[2*nproc]
  2890                              <1> ;	p.break:.=.+[2*nproc]
  2891                              <1> ;	p.link: .=.+nproc
  2892                              <1> ;	p.stat: .=.+nproc
  2893                              <1> ;tty:
  2894                              <1> ;	. = .+[ntty*8.]
  2895                              <1> ;fsp:	.=.+[nfiles*8.]
  2896                              <1> ;bufp:	.=.+[nbuf*2]+6
  2897                              <1> ;sb0:	.=.+8
  2898                              <1> ;sb1:	.=.+8
  2899                              <1> ;swp:	.=.+8
  2900                              <1> ;ii:	.=.+2
  2901                              <1> ;idev:	.=.+2
  2902                              <1> ;cdev:	.=.+2
  2903                              <1> ;deverr: .=.+12.
  2904                              <1> ;active: .=.+2
  2905                              <1> ;rfap:	.=.+2
  2906                              <1> ;rkap:	.=.+2
  2907                              <1> ;tcap:	.=.+2
  2908                              <1> ;tcstate:.=.+2
  2909                              <1> ;tcerrc: .=.+2
  2910                              <1> ;mnti:	.=.+2
  2911                              <1> ;mntd:	.=.+2
  2912                              <1> ;mpid:	.=.+2
  2913                              <1> ;clockp: .=.+2
  2914                              <1> ;rootdir:.=.+2
  2915                              <1> ;toutt:	.=.+16.
  2916                              <1> ;touts: .=.+32.
  2917                              <1> ;runq:	.=.+6
  2918                              <1> ;
  2919                              <1> ;wlist:	.=.+40.
  2920                              <1> ;cc:	.=.+30.
  2921                              <1> ;cf:	.=.+31.
  2922                              <1> ;cl:	.=.+31.
  2923                              <1> ;clist:	.=.+510.
  2924                              <1> ;imod:	.=.+1
  2925                              <1> ;smod:	.=.+1
  2926                              <1> ;mmod:	.=.+1
  2927                              <1> ;uquant: .=.+1
  2928                              <1> ;sysflg: .=.+1
  2929                              <1> ;pptiflg:.=.+1
  2930                              <1> ;ttyoch: .=.+1
  2931                              <1> ; .even
  2932                              <1> ; .=.+100.; sstack:
  2933                              <1> ;buffer: .=.+[ntty*140.]
  2934                              <1> ;	.=.+[nbuf*520.]
  2935                              <1> ;
  2936                              <1> ; . = core-64.
  2937                              <1> ;user:
  2938                              <1> ;	u.sp:    .=.+2
  2939                              <1> ;	u.usp:   .=.+2
  2940                              <1> ;	u.r0:    .=.+2
  2941                              <1> ;	u.cdir:  .=.+2
  2942                              <1> ;	u.fp:    .=.+10.
  2943                              <1> ;	u.fofp:  .=.+2
  2944                              <1> ;	u.dirp:  .=.+2
  2945                              <1> ;	u.namep: .=.+2
  2946                              <1> ;	u.off:   .=.+2
  2947                              <1> ;	u.base:  .=.+2
  2948                              <1> ;	u.count: .=.+2
  2949                              <1> ;	u.nread: .=.+2
  2950                              <1> ;	u.break: .=.+2
  2951                              <1> ;	u.ttyp:  .=.+2
  2952                              <1> ;	u.dirbuf:.=.+10.
  2953                              <1> ;	u.pri:   .=.+2
  2954                              <1> ;	u.intr:  .=.+2
  2955                              <1> ;	u.quit:  .=.+2
  2956                              <1> ;	u.emt:   .=.+2
  2957                              <1> ;	u.ilgins:.=.+2
  2958                              <1> ;	u.cdev:  .=.+2
  2959                              <1> ;	u.uid:   .=.+1
  2960                              <1> ;	u.ruid:  .=.+1
  2961                              <1> ;	u.bsys:  .=.+1
  2962                              <1> ;	u.uno:   .=.+1
  2963                              <1> ;. = core
  2621                                  
  2622                                  ; 24/12/2021
  2623                                  ; (memory page swap parameters are disabled as temporary)
  2624                                  ;
  2625                                  ;; Memory (swap) Data (11/03/2015)
  2626                                  ; 09/03/2015
  2627                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2628                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2629                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2630                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2631                                  ;swpd_next:  resd 1 ; next free page block
  2632                                  ;swpd_last:  resd 1 ; last swap page block	
  2633                                  	
  2634                                  
  2635                                  alignb 4
  2636                                  
  2637                                  ; 10/07/2015
  2638                                  ; 28/08/2014
  2639 000080D0 ????????                error_code:	resd 1
  2640                                  ; 29/08/2014
  2641 000080D4 ????????                FaultOffset: 	resd 1
  2642                                  ; 21/09/2015
  2643 000080D8 ????????                PF_Count:	resd 1	; total page fault count
  2644                                  		       	; (for debugging - page fault analyze)
  2645                                  		 	; 'page _fault_handler' (memory.inc)
  2646                                  			; 'sysgeterr' (u9.s)
  2647                                  ;; 21/08/2015
  2648                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2649                                  
  2650                                  bss_end:
  2651                                  
  2652                                  ; 27/12/2013
  2653                                  _end:  ; end of kernel code (and read only data, just before bss)
