1 ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2 ; (re-write kernel for test by using previous version without a major defect) 3 ; **************************************************************************** 4 ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.2.4 5 ; ---------------------------------------------------------------------------- 6 ; NASM version 2.15 (unix386.s) 7 ; 8 ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix) 9 ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013) 10 ; 11 ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 12 ; (v0.1 - Beginning: 11/07/2012) 13 ; 14 ; [ Last Modification: 27/12/2022 ] 15 ; 16 ; Derived from UNIX Operating System (v1.0 for PDP-11) 17 ; (Original) Source Code by Ken Thompson (1971-1972) 18 ; 19 ; 20 ; 21 ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999) 22 ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details. 23 ; 24 ; **************************************************************************** 25 26 ; 24/12/2013 27 28 ; Entering protected mode: 29 ; Derived from 'simple_asm.txt' source code file and 30 ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003) 31 ; (gregor.brunmar@home.se) 32 ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode 33 ; 34 35 ; "The Real, Protected, Long mode assembly tutorial for PCs" 36 ; by Michael Chourdakis (2009) 37 ; http://www.codeproject.com/Articles/45788/ 38 ; http://www.michaelchourdakis.com 39 ; 40 41 ; Global Descriptor Table: 42 ; Derived from 'head.s" source code of Linux v1.0 kernel 43 ; by Linus Torvalds (1991-1992) 44 ; 45 46 KLOAD equ 10000h ; Kernel loading address 47 ; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 48 KCODE equ 08h ; Code segment descriptor (ring 0) 49 KDATA equ 10h ; Data segment descriptor (ring 0) 50 ; 19/03/2015 51 UCODE equ 1Bh ; 18h + 3h (ring 3) 52 UDATA equ 23h ; 20h + 3h (ring 3) 53 ; 24/03/2015 54 TSS equ 28h ; Task state segment descriptor (ring 0) 55 ; 19/03/2015 56 CORE equ 400000h ; Start of USER's virtual/linear address space 57 ; (at the end of the 1st 4MB) 58 ECORE equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB) 59 ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT) 60 61 ; 01/01/2022 (Retro UNIX 386 v1.2) 62 ;; 27/12/2013 63 ;KEND equ KLOAD + 65536 ; (28/12/2013) (end of kernel space) 64 65 ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc) 66 ;--------- CMOS TABLE LOCATION ADDRESS'S ------------------------------------- 67 CMOS_SECONDS EQU 00H ; SECONDS (BCD) 68 CMOS_MINUTES EQU 02H ; MINUTES (BCD) 69 CMOS_HOURS EQU 04H ; HOURS (BCD) 70 CMOS_DAY_WEEK EQU 06H ; DAY OF THE WEEK (BCD) 71 CMOS_DAY_MONTH EQU 07H ; DAY OF THE MONTH (BCD) 72 CMOS_MONTH EQU 08H ; MONTH (BCD) 73 CMOS_YEAR EQU 09H ; YEAR (TWO DIGITS) (BCD) 74 CMOS_CENTURY EQU 32H ; DATE CENTURY BYTE (BCD) 75 CMOS_REG_A EQU 0AH ; STATUS REGISTER A 76 CMOS_REG_B EQU 00BH ; STATUS REGISTER B ALARM 77 CMOS_REG_C EQU 00CH ; STATUS REGISTER C FLAGS 78 CMOS_REG_D EQU 0DH ; STATUS REGISTER D BATTERY 79 CMOS_SHUT_DOWN EQU 0FH ; SHUTDOWN STATUS COMMAND BYTE 80 ;---------------------------------------- 81 ; CMOS EQUATES FOR THIS SYSTEM ; 82 ;----------------------------------------------------------------------------- 83 CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 84 CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 85 NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 86 ; HIGH BIT OF CMOS LOCATION ADDRESS 87 88 ; Memory Allocation Table Address 89 ; 05/11/2014 90 ; 31/10/2014 91 MEM_ALLOC_TBL equ 100000h ; Memory Allocation Table at the end of 92 ; the 1st 1 MB memory space. 93 ; (This address must be aligned 94 ; on 128 KB boundary, if it will be 95 ; changed later.) 96 ; ((lower 17 bits of 32 bit M.A.T. 97 ; address must be ZERO)). 98 ; ((((Reason: 32 bit allocation 99 ; instructions, dword steps))) 100 ; (((byte >> 12 --> page >> 5))) 101 ;04/11/2014 102 PDE_A_PRESENT equ 1 ; Present flag for PDE 103 PDE_A_WRITE equ 2 ; Writable (write permission) flag 104 PDE_A_USER equ 4 ; User (non-system/kernel) page flag 105 ; 106 PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 107 PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 108 PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 109 PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 110 111 ; 17/02/2015 (unix386.s) 112 ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s) 113 DPT_SEGM equ 09000h ; FDPT segment (EDD v1.1, EDD v3) 114 ; 115 HD0_DPT equ 0 ; Disk parameter table address for hd0 116 HD1_DPT equ 32 ; Disk parameter table address for hd1 117 HD2_DPT equ 64 ; Disk parameter table address for hd2 118 HD3_DPT equ 96 ; Disk parameter table address for hd3 119 120 121 ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0) 122 ; (HDPT: Programmer's Guide to the AMIBIOS, 1993) 123 ; 124 FDPT_CYLS equ 0 ; 1 word, number of cylinders 125 FDPT_HDS equ 2 ; 1 byte, number of heads 126 FDPT_TT equ 3 ; 1 byte, A0h = translated FDPT with logical values 127 ; otherwise it is standard FDPT with physical values 128 FDPT_PCMP equ 5 ; 1 word, starting write precompensation cylinder 129 ; (obsolete for IDE/ATA drives) 130 FDPT_CB equ 8 ; 1 byte, drive control byte 131 ; Bits 7-6 : Enable or disable retries (00h = enable) 132 ; Bit 5 : 1 = Defect map is located at last cyl. + 1 133 ; Bit 4 : Reserved. Always 0 134 ; Bit 3 : Set to 1 if more than 8 heads 135 ; Bit 2-0 : Reserved. Alsways 0 136 FDPT_LZ equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives) 137 FDPT_SPT equ 14 ; 1 byte, sectors per track 138 139 ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993) 140 ; (11 bytes long) will be used by diskette handler/bios 141 ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986). 142 143 [BITS 16] ; We need 16-bit intructions for Real mode 144 145 [ORG 0] 146 147 KSTART: ; 01/01/2022 148 149 ; 12/11/2014 150 ; Save boot drive number (that is default root drive) 151 00000000 8816[8862] mov [boot_drv], dl ; physical drv number 152 153 ; Determine installed memory 154 ; 31/10/2014 155 ; 156 00000004 B801E8 mov ax, 0E801h ; Get memory size 157 00000007 CD15 int 15h ; for large configurations 158 00000009 7308 jnc short chk_ms 159 0000000B B488 mov ah, 88h ; Get extended memory size 160 0000000D CD15 int 15h 161 ; 162 ;mov al, 17h ; Extended memory (1K blocks) low byte 163 ;out 70h, al ; select CMOS register 164 ;in al, 71h ; read data (1 byte) 165 ;mov cl, al 166 ;mov al, 18h ; Extended memory (1K blocks) high byte 167 ;out 70h, al ; select CMOS register 168 ;in al, 71h ; read data (1 byte) 169 ;mov ch, al 170 ; 171 0000000F 89C1 mov cx, ax 172 00000011 31D2 xor dx, dx 173 chk_ms: 174 00000013 890E[F464] mov [mem_1m_1k], cx 175 00000017 8916[F864] mov [mem_16m_64k], dx 176 ; 05/11/2014 177 ;and dx, dx 178 ;jz short L2 179 0000001B 81F90004 cmp cx, 1024 180 0000001F 7351 jnb short L0 181 ; insufficient memory_error 182 ; Minimum 2 MB memory is needed... 183 oom_0: 184 ; 05/11/2014 185 ; (real mode error printing) 186 00000021 FB sti 187 00000022 BE[3600] 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 ; 28/11/2021 - Retro UNIX 386 v2 compatibility modification (on v1.1) 201 ; 11/04/2021 - Retro UNIX 386 v2 202 ; ((Real mode messages and buffers must be in the 1st 64K of the kernel)) 203 ; 20/02/2017 (TRDOS 386 v2) 204 ; 05/11/2014 205 msg_out_of_memory: 206 00000036 070D0A db 07h, 0Dh, 0Ah 207 00000039 496E73756666696369- db 'Insufficient memory !' 208 00000042 656E74206D656D6F72- 209 0000004B 792021 210 0000004E 0D0A db 0Dh, 0Ah 211 _int13h_48h_buffer: ; 07/07/2016 212 00000050 284D696E696D756D20- db '(Minimum 2MB memory is needed.)' 213 00000059 324D42206D656D6F72- 214 00000062 79206973206E656564- 215 0000006B 65642E29 216 0000006F 0D0A00 db 0Dh, 0Ah, 0 217 218 L0: 219 %include 'diskinit.s' ; 07/03/2015 220 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 221 <1> ; (re-write kernel for test by using previous version without a major defect) 222 <1> ; **************************************************************************** 223 <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - DISKINIT.INC 224 <1> ; Last Modification: 08/08/2022 (Previous: 12/07/2022) 225 <1> 226 <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project) 227 <1> 228 <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION /////////////// 229 <1> 230 <1> ; 08/08/2022 231 <1> ; 14/07/2022 (TRDOS 386 v2.0.5) 232 <1> ; 12/07/2022 233 <1> ; 02/01/2022 (Retro UNIX 386 v1.2) 234 <1> ; 29/08/2020 235 <1> ; 17/07/2020 236 <1> ; 14/07/2020 (TRDOS 386 v2.0.2) 237 <1> ; 06/02/2015 (Retro UNIX 386 v1) 238 <1> ; 10/12/2014 - 02/02/2015 - dsectrm2.s 239 <1> ;L0: 240 <1> ; 12/11/2014 (Retro UNIX 386 v1 - beginning) 241 <1> ; Detecting disk drives... (by help of ROM-BIOS) 242 00000072 BA7F00 <1> mov dx, 7Fh 243 <1> L1: 244 00000075 FEC2 <1> inc dl 245 00000077 B441 <1> mov ah, 41h ; Check extensions present 246 <1> ; Phoenix EDD v1.1 - EDD v3 247 00000079 BBAA55 <1> mov bx, 55AAh 248 0000007C CD13 <1> int 13h 249 0000007E 721A <1> jc short L2 250 <1> 251 00000080 81FB55AA <1> cmp bx, 0AA55h 252 00000084 7514 <1> jne short L2 253 00000086 FE06[8B62] <1> inc byte [hdc] ; count of hard disks (EDD present) 254 0000008A 8816[8A62] <1> mov [last_drv], dl ; last hard disk number 255 0000008E BB[0E62] <1> mov bx, hd0_type - 80h 256 00000091 01D3 <1> add bx, dx 257 00000093 880F <1> mov [bx], cl ; Interface support bit map in CX 258 <1> ; Bit 0 - 1, Fixed disk access subset ready 259 <1> ; Bit 1 - 1, Drv locking and ejecting ready 260 <1> ; Bit 2 - 1, Enhanced Disk Drive Support 261 <1> ; (EDD) ready (DPTE ready) 262 <1> ; Bit 3 - 1, 64bit extensions are present 263 <1> ; (EDD-3) 264 <1> ; Bit 4 to 15 - 0, Reserved 265 00000095 80FA83 <1> cmp dl, 83h ; drive number < 83h 266 00000098 72DB <1> jb short L1 267 <1> L2: 268 <1> ; 23/11/2014 269 <1> ; 19/11/2014 270 0000009A 30D2 <1> xor dl, dl ; 0 271 <1> ; 04/02/2016 (esi -> si) 272 0000009C BE[8C62] <1> mov si, fd0_type 273 <1> L3: 274 <1> ; 14/01/2015 275 0000009F 8816[8962] <1> mov [drv], dl 276 <1> ; 277 000000A3 B408 <1> mov ah, 08h ; Return drive parameters 278 000000A5 CD13 <1> int 13h 279 000000A7 7210 <1> jc short L4 280 <1> ; BL = drive type (for floppy drives) 281 <1> ; DL = number of floppy drives 282 <1> ; 283 <1> ; ES:DI = Address of DPT from BIOS 284 <1> ; 285 000000A9 881C <1> mov [si], bl ; Drive type 286 <1> ; 4 = 1.44 MB, 80 track, 3 1/2" 287 <1> ; 14/01/2015 288 000000AB E8DC01 <1> call set_disk_parms 289 <1> ; 10/12/2014 290 000000AE 81FE[8C62] <1> cmp si, fd0_type 291 000000B2 7705 <1> ja short L4 292 000000B4 46 <1> inc si ; fd1_type 293 000000B5 B201 <1> mov dl, 1 294 000000B7 EBE6 <1> jmp short L3 295 <1> L4: 296 000000B9 B27F <1> mov dl, 7Fh 297 <1> ; 24/12/2014 298 000000BB 803E[8B62]00 <1> cmp byte [hdc], 0 ; EDD present or not ? 299 <1> ;ja L10 ; yes, all fixed disk operations 300 <1> ; will be performed according to 301 <1> ; present EDD specification 302 <1> ; 14/07/2022 303 000000C0 7603 <1> jna short L5 304 000000C2 E98800 <1> jmp L10 305 <1> 306 <1> L5: 307 <1> ; 17/07/2020 308 <1> ; Note: Virtual CPU will not come here while 309 <1> ; running in QEMU, Bochs, VirtualBox emulators !!! 310 <1> 311 <1> ; 17/07/2020 312 <1> ; Older BIOS (INT 13h, AH = 48h is not available) 313 <1> 314 000000C5 FEC2 <1> inc dl 315 000000C7 8816[8962] <1> mov [drv], dl 316 000000CB 8816[8A62] <1> mov [last_drv], dl ; 14/01/2015 317 000000CF B408 <1> mov ah, 08h ; Return drive parameters 318 000000D1 CD13 <1> int 13h ; (conventional function) 319 <1> ;jc L13 ; fixed disk drive not ready 320 <1> ; 14/07/2022 321 000000D3 7303 <1> jnc short L6 322 000000D5 E9A401 <1> jmp L13 323 <1> L6: 324 000000D8 8816[8B62] <1> mov [hdc], dl ; number of drives 325 <1> ;; 14/01/2013 326 <1> ;;push cx 327 000000DC E8AB01 <1> call set_disk_parms 328 <1> ;;pop cx 329 <1> ; 330 <1> ;;and cl, 3Fh ; sectors per track (bits 0-6) 331 000000DF 8A16[8962] <1> mov dl, [drv] 332 000000E3 BB0401 <1> mov bx, 65*4 ; hd0 parameters table (INT 41h) 333 000000E6 80FA80 <1> cmp dl, 80h 334 000000E9 7603 <1> jna short L7 335 000000EB 83C314 <1> add bx, 5*4 ; hd1 parameters table (INT 46h) 336 <1> L7: 337 000000EE 31C0 <1> xor ax, ax 338 000000F0 8ED8 <1> mov ds, ax 339 000000F2 8B37 <1> mov si, [bx] 340 000000F4 8B4702 <1> mov ax, [bx+2] 341 000000F7 8ED8 <1> mov ds, ax 342 000000F9 3A4C0E <1> cmp cl, [si+FDPT_SPT] ; sectors per track 343 <1> ;jne L12 ; invalid FDPT 344 <1> ; 14/07/2022 345 000000FC 7403 <1> je short L7_8 346 000000FE E97701 <1> jmp L12 347 <1> L7_8: 348 00000101 BF0000 <1> mov di, HD0_DPT 349 00000104 80FA80 <1> cmp dl, 80h 350 00000107 7603 <1> jna short L8 351 00000109 BF2000 <1> mov di, HD1_DPT 352 <1> L8: 353 <1> ; 30/12/2014 354 0000010C B80090 <1> mov ax, DPT_SEGM 355 0000010F 8EC0 <1> mov es, ax 356 <1> ; 24/12/2014 357 00000111 B90800 <1> mov cx, 8 358 00000114 F3A5 <1> rep movsw ; copy 16 bytes to the kernel's DPT location 359 00000116 8CC8 <1> mov ax, cs 360 00000118 8ED8 <1> mov ds, ax 361 <1> 362 <1> ; 02/02/2015 363 <1> ;mov cl, [drv] 364 <1> ;mov bl, cl 365 <1> ;mov ax, 1F0h 366 <1> ;and bl, 1 367 <1> ;jz short L9 368 <1> ;shl bl, 4 369 <1> ;sub ax, 1F0h-170h 370 <1> 371 <1> ; 17/07/2020 372 <1> ; (Only 1F0h port address must be valid for old ROM BIOSes) 373 0000011A B8F001 <1> mov ax, 1F0h 374 0000011D B3A0 <1> mov bl, 0A0h 375 0000011F 80FA80 <1> cmp dl, 80h 376 00000122 7603 <1> jna short L9 377 <1> ; dl = 81h 378 00000124 80C310 <1> add bl, 10h ; slave disk 379 <1> ;sub ax, 1F0h-170h 380 <1> L9: 381 00000127 AB <1> stosw ; I/O PORT Base Address (1F0h, 170h) 382 00000128 050602 <1> add ax, 206h 383 0000012B AB <1> stosw ; CONTROL PORT Address (3F6h, 376h) 384 0000012C 88D8 <1> mov al, bl ; bit 4, master/slave disk bit 385 <1> ;add al, 0A0h ; 17/07/2020 386 0000012E AA <1> stosb ; Device/Head Register upper nibble 387 <1> ; 388 0000012F FE06[8962] <1> inc byte [drv] 389 00000133 BB[0E62] <1> mov bx, hd0_type - 80h 390 00000136 01CB <1> add bx, cx 391 00000138 800F80 <1> or byte [bx], 80h ; present sign (when lower nibble is 0) 392 0000013B A0[8B62] <1> mov al, [hdc] 393 0000013E FEC8 <1> dec al 394 <1> ;jz L13 395 <1> ; 14/07/2022 396 00000140 7408 <1> jz short L9_10 397 00000142 80FA80 <1> cmp dl, 80h 398 <1> ;jna L5 ; Max. 2 hard disks ; 17/07/2020 399 <1> ; 14/07/2022 400 00000145 7703 <1> ja short L9_10 401 00000147 E97BFF <1> jmp L5 402 <1> L9_10: 403 0000014A E92F01 <1> jmp L13 404 <1> L10: 405 0000014D FEC2 <1> inc dl 406 <1> ; 25/12/2014 407 0000014F 8816[8962] <1> mov [drv], dl 408 00000153 B408 <1> mov ah, 08h ; Return drive parameters 409 00000155 CD13 <1> int 13h ; (conventional function) 410 <1> ;jc L13 411 <1> ; 14/07/2022 412 00000157 72F1 <1> jc short L9_10 413 <1> ; 14/01/2015 414 00000159 8A16[8962] <1> mov dl, [drv] 415 0000015D 52 <1> push dx 416 0000015E 51 <1> push cx 417 0000015F E82801 <1> call set_disk_parms 418 00000162 59 <1> pop cx 419 00000163 5A <1> pop dx 420 <1> ; 06/07/2016 (BugFix for >64K kernel files) 421 <1> ; 04/02/2016 (esi -> si) 422 <1> ;mov si, _end ; 30 byte temporary buffer address 423 <1> ; ; at the '_end' of kernel. 424 <1> ;mov word [si], 30 425 <1> ; 06/07/2016 426 00000164 BE[5000] <1> mov si, _int13h_48h_buffer 427 <1> ; 09/07/2016 428 00000167 B81E00 <1> mov ax, 001Eh 429 0000016A 8824 <1> mov [si], ah ; 0 430 0000016C 46 <1> inc si 431 0000016D 8904 <1> mov word [si], ax 432 <1> ; word [si] = 30 433 <1> ; 434 0000016F B448 <1> mov ah, 48h ; Get drive parameters (EDD function) 435 00000171 CD13 <1> int 13h 436 <1> ;jc L13 437 <1> ; 14/07/2022 438 00000173 72D5 <1> jc short L9_10 439 <1> 440 <1> ; 29/08/2020 441 <1> ; 04/02/2016 (ebx -> bx) 442 <1> ; 14/01/2015 443 00000175 28FF <1> sub bh, bh 444 00000177 88D3 <1> mov bl, dl 445 <1> ;sub bl, 80h 446 <1> ; 29/08/2020 447 00000179 81C3[0E62] <1> add bx, (hd0_type - 80h) 448 <1> ;mov al, [bx] 449 0000017D 8A07 <1> mov al, [bx] 450 0000017F 0C80 <1> or al, 80h 451 00000181 8807 <1> mov [bx], al 452 00000183 81EB[8C62] <1> sub bx, hd0_type - 2 ; 15/01/2015 453 <1> ;add bx, drv.status 454 <1> ;mov [bx], al 455 <1> ; 29/08/2020 456 00000187 8887[AE62] <1> mov [bx+drv.status], al 457 <1> ; 04/02/2016 (eax -> ax) 458 <1> ;mov ax, [si+16] 459 <1> ; 14/07/2020 460 <1> ;mov di, [si+18] 461 <1> ;;test ax, [si+18] 462 <1> ;test ax, di ; 14/07/2020 463 <1> ;jz short L10_A0h ; (!) ; 17/07/2020 464 <1> ; 'CHS only' disks on EDD system 465 <1> ; are reported with ZERO disk size 466 <1> ; (if so, we must not overwrite 467 <1> ; calculated disk size in 'set_disk_parms') 468 <1> ; 29/08/2020 469 0000018B 8B4410 <1> mov ax, [si+16] 470 0000018E 8B7C12 <1> mov di, [si+18] 471 00000191 09C0 <1> or ax, ax 472 00000193 7504 <1> jnz short L10_LBA 473 00000195 09FF <1> or di, di 474 00000197 740B <1> jz short L10_A0h 475 <1> L10_LBA: 476 <1> ;sub bx, drv.status 477 00000199 C1E302 <1> shl bx, 2 478 <1> ;add bx, drv.size ; disk size (in sectors) 479 <1> ;mov [bx], ax 480 <1> ; 29/08/2020 481 0000019C 8987[9262] <1> mov [bx+drv.size], ax 482 <1> ;mov ax, [si+18] 483 <1> ;;mov [bx], ax 484 <1> ;mov [bx+2], ax ; BugFix ; 15/07/2020 485 <1> ; 14/07/2020 486 <1> ;mov [bx+2], di ; 15/07/2020 487 <1> ; 29/08/2020 488 000001A0 89BF[9462] <1> mov [bx+drv.size+2], di 489 <1> L10_A0h: 490 <1> ; 17/07/2020 491 <1> ; Note: Virtual CPU will jump here from above (!) test 492 <1> ; while running in QEMU 493 <1> 494 <1> ; Jump here to fix a ZERO (LBA) disk size problem 495 <1> ; for CHS disks (28/02/2015) 496 <1> 497 <1> ; 30/12/2014 498 000001A4 BF0000 <1> mov di, HD0_DPT 499 000001A7 88D0 <1> mov al, dl 500 000001A9 83E003 <1> and ax, 3 501 000001AC C0E005 <1> shl al, 5 ; * 32 502 000001AF 01C7 <1> add di, ax 503 000001B1 B80090 <1> mov ax, DPT_SEGM 504 000001B4 8EC0 <1> mov es, ax 505 <1> ; 506 000001B6 88E8 <1> mov al, ch ; max. cylinder number (bits 0-7) 507 000001B8 88CC <1> mov ah, cl 508 000001BA C0EC06 <1> shr ah, 6 ; max. cylinder number (bits 8-9) 509 000001BD 40 <1> inc ax ; logical cylinders (limit 1024) 510 000001BE AB <1> stosw 511 000001BF 88F0 <1> mov al, dh ; max. head number 512 <1> ; 513 000001C1 30F6 <1> xor dh, dh ; 29/08/2020 (dh = 0 is needed here) 514 <1> ; 515 000001C3 FEC0 <1> inc al 516 000001C5 AA <1> stosb ; logical heads (limits 256) 517 000001C6 B0A0 <1> mov al, 0A0h ; Indicates translated table 518 000001C8 AA <1> stosb 519 000001C9 8A440C <1> mov al, [si+12] 520 000001CC AA <1> stosb ; physical sectors per track 521 000001CD 31C0 <1> xor ax, ax 522 <1> ;dec ax ; 02/01/2015 523 000001CF AB <1> stosw ; precompensation (obsolete) 524 <1> ;xor al, al ; 02/01/2015 525 000001D0 AA <1> stosb ; reserved 526 000001D1 B008 <1> mov al, 8 ; drive control byte 527 <1> ; (do not disable retries, 528 <1> ; more than 8 heads) 529 000001D3 AA <1> stosb 530 000001D4 8B4404 <1> mov ax, [si+4] 531 000001D7 AB <1> stosw ; physical number of cylinders 532 <1> ;push ax ; 02/01/2015 533 000001D8 8A4408 <1> mov al, [si+8] 534 000001DB AA <1> stosb ; physical num. of heads (limit 16) 535 000001DC 29C0 <1> sub ax, ax 536 <1> ;pop ax ; 02/01/2015 537 000001DE AB <1> stosw ; landing zone (obsolete) 538 000001DF 88C8 <1> mov al, cl ; logical sectors per track (limit 63) 539 000001E1 243F <1> and al, 3Fh 540 000001E3 AA <1> stosb 541 <1> ;sub al, al ; checksum 542 <1> ;stosb 543 <1> ; 544 000001E4 83C61A <1> add si, 26 ; (BIOS) DPTE address pointer 545 000001E7 AD <1> lodsw 546 000001E8 50 <1> push ax ; * ; (BIOS) DPTE offset 547 000001E9 AD <1> lodsw 548 000001EA 50 <1> push ax ; ** ; (BIOS) DPTE segment 549 <1> ; 550 <1> ; checksum calculation 551 000001EB 89FE <1> mov si, di 552 000001ED 06 <1> push es 553 000001EE 1F <1> pop ds 554 <1> ;mov cx, 16 555 000001EF B90F00 <1> mov cx, 15 556 000001F2 29CE <1> sub si, cx 557 000001F4 30E4 <1> xor ah, ah 558 <1> ;del cl 559 <1> L11: 560 000001F6 AC <1> lodsb 561 000001F7 00C4 <1> add ah, al 562 000001F9 E2FB <1> loop L11 563 <1> ; 564 000001FB 88E0 <1> mov al, ah 565 000001FD F6D8 <1> neg al ; -x+x = 0 566 000001FF AA <1> stosb ; put checksum in byte 15 of the tbl 567 <1> ; 568 00000200 1F <1> pop ds ; ** ; (BIOS) DPTE segment 569 00000201 5E <1> pop si ; * ; (BIOS) DPTE offset 570 <1> 571 <1> ; 08/08/2022 (TRDOS 386 v2.0.5) 572 <1> ; (Recent version of Retro UNIX 386 v1 'diskinit.s' file 573 <1> ; -12/07/2022- does not contain following 2020 code) (*) 574 <1> 575 <1> ; 14/07/2020 (TRDOS 386 v2.0.2) 576 <1> ; 0FFFFh:0FFFFh = invalid DPTE address 577 00000202 8B0C <1> mov cx, [si] 578 00000204 8B4402 <1> mov ax, [si+2] 579 00000207 21C1 <1> and cx, ax 580 00000209 41 <1> inc cx 581 0000020A 7404 <1> jz short L11c ; 0FFFFh:0FFFFh 582 0000020C 0B04 <1> or ax, [si] 583 0000020E 752A <1> jnz short L11e ; <> 0 584 <1> L11c: 585 <1> ; 17/07/2020 586 <1> ; TRDOS 386 v2 DRVINIT assumptions: 587 <1> ; (also by regarding QEMU, Bochs and VirtualBox settings) 588 <1> ; Hard disk 0 port address: 1F0h 589 <1> ; Hard disk 1 port address: 1F0h 590 <1> ; Hard disk 2 port address: 170h 591 <1> ; Hard disk 3 port address: 170h 592 <1> 593 <1> ; in QEMU, hda=hd0 (1F0h) and hdb=hd1 (1F0h) -IRQ14- 594 <1> ; and hdc=hd2 (170h) and hdd=hd3 (170h) -IRQ15- 595 <1> 596 00000210 B8F001 <1> mov ax, 1F0h 597 <1> 598 <1> ; 15/07/2020 599 <1> ; 14/07/2020 600 <1> ; Invalid DPTE address... 601 <1> ; Default DPTE parms must be set for DISK_IO_CONT 602 <1> ; (diskio.s) 603 <1> ; 17/07/2020 604 <1> 605 <1> ;mov bl, dl 606 <1> ;and bl, 1 607 <1> ;jz short L11d 608 <1> 609 00000213 B3A0 <1> mov bl, 0A0h 610 <1> 611 00000215 F6C201 <1> test dl, 1 612 00000218 7403 <1> jz short L11g ; Master (as default, for 80h & 82h)) 613 <1> ;shl bl, 4 ; bl = 16 (bit 4 = 1 -> slave) 614 0000021A 80C310 <1> add bl, 10h ; Slave (as default, for 81h & 83h) 615 <1> L11g: 616 <1> ; 17/07/2020 617 0000021D 80FA82 <1> cmp dl, 82h ; Hard disk 3 or 4 ? 618 00000220 7203 <1> jb short L11d ; Primary ATA channel (hd0, hd1) 619 <1> ; (port address = 1F0h) 620 <1> 621 <1> ; Secondary ATA channel (hd2, hd3) 622 <1> ; (port address = 170h) 623 <1> 624 00000222 2D8000 <1> sub ax, 1F0h-170h 625 <1> L11d: 626 <1> ; 14/07/2020 627 00000225 AB <1> stosw ; I/O PORT Base Address (1F0h, 170h) 628 00000226 050602 <1> add ax, 206h 629 00000229 AB <1> stosw ; CONTROL PORT Address (3F6h, 376h) 630 0000022A 88D8 <1> mov al, bl ; Master/Slave bit (0 = Master) 631 <1> ; 17/07/2020 632 <1> ;or al, 0A0h ; CHS (LBA enable bit = 0) 633 <1> ; (Bits 5&7, reserved bits = 1) 634 0000022C 30E4 <1> xor ah, ah 635 <1> ;stosb ; Device/Head Register upper nibble 636 0000022E AB <1> stosw 637 0000022F 30C0 <1> xor al, al 638 00000231 B90500 <1> mov cx, 5 639 00000234 F3AB <1> rep stosw ; clear remain part of the (fake) DPTE 640 00000236 0E <1> push cs 641 00000237 1F <1> pop ds 642 00000238 EB2E <1> jmp short L11f 643 <1> 644 <1> ; 08/08/2022 (TRDOS 386 v2.0.5) 645 <1> ; (Recent version of Retro UNIX 386 v1 'diskinit.s' file 646 <1> ; -12/07/2022- does not contain above 2020 code) (*) 647 <1> L11e: 648 <1> ; 23/02/2015 649 0000023A 57 <1> push di 650 <1> ; ES:DI points to DPTE (FDPTE) location 651 <1> ;;mov cx, 8 652 <1> ;mov cl, 8 653 0000023B B90800 <1> mov cx, 8 ; 14/07/2020 654 0000023E F3A5 <1> rep movsw 655 <1> ; 656 <1> ; 23/02/2015 657 <1> ; (P)ATA drive and LBA validation 658 <1> ; (invalidating SATA drives and setting 659 <1> ; CHS type I/O for old type fixed disks) 660 00000240 5B <1> pop bx 661 00000241 8CC8 <1> mov ax, cs 662 00000243 8ED8 <1> mov ds, ax 663 00000245 268B07 <1> mov ax, [es:bx] 664 00000248 3DF001 <1> cmp ax, 1F0h 665 0000024B 7413 <1> je short L11a 666 0000024D 3D7001 <1> cmp ax, 170h 667 00000250 740E <1> je short L11a 668 <1> ; invalidation 669 <1> ; (because base port address is not 1F0h or 170h) 670 <1> ;xor bh, bh 671 <1> ;mov bl, dl 672 <1> ; 29/08/2020 673 <1> ;xor dh, dh ; 0 674 00000252 89D3 <1> mov bx, dx 675 <1> ;sub bl, 80h 676 <1> ;mov byte [bx+hd0_type], 0 ; not a valid disk drive ! 677 <1> ;or byte [bx+drv.status+2], 0F0h ; (failure sign) 678 <1> ; 29/08/2020 679 00000254 C687[0E62]00 <1> mov byte [bx+hd0_type-80h], 0 680 00000259 808F[3062]F0 <1> or byte [bx+drv.status-7Eh], 0F0h 681 0000025E EB0F <1> jmp short L11b 682 <1> L11a: 683 <1> ; LBA validation 684 00000260 268A4704 <1> mov al, [es:bx+4] ; Head register upper nibble 685 00000264 A840 <1> test al, 40h ; LBA bit (bit 6) 686 00000266 7507 <1> jnz short L11b ; LBA type I/O is OK! (E0h or F0h) 687 <1> L11f: 688 <1> ; force CHS type I/O for this drive (A0h or B0h) 689 <1> ;sub bh, bh 690 <1> ;mov bl, dl 691 <1> ; 29/08/2020 692 <1> ;xor dh, dh ; 0 693 00000268 89D3 <1> mov bx, dx 694 <1> ;sub bl, 80h ; 26/02/2015 695 <1> ;and byte [bx+drv.status+2], 0FEh ; clear bit 0 696 <1> ; bit 0 = LBA ready bit 697 <1> ; 29/08/2020 698 0000026A 80A7[3062]FE <1> and byte [bx+drv.status-7Eh], 0FEh 699 <1> ; 'diskio' procedure will check this bit ! 700 <1> L11b: 701 0000026F 3A16[8A62] <1> cmp dl, [last_drv] ; 25/12/2014 702 00000273 7307 <1> jnb short L13 703 00000275 E9D5FE <1> jmp L10 704 <1> 705 <1> L12: 706 <1> ; Restore data registers 707 00000278 8CC8 <1> mov ax, cs 708 0000027A 8ED8 <1> mov ds, ax 709 <1> L13: 710 <1> ; 13/12/2014 711 0000027C 0E <1> push cs 712 0000027D 07 <1> pop es 713 <1> L14: 714 <1> ; clear keyboard buffer 715 0000027E B411 <1> mov ah, 11h 716 00000280 CD16 <1> int 16h 717 00000282 7440 <1> jz short L16 ; no keys in keyboard buffer 718 00000284 B010 <1> mov al, 10h 719 00000286 CD16 <1> int 16h 720 00000288 EBF4 <1> jmp short L14 721 <1> 722 <1> set_disk_parms: 723 <1> ; 08/08/2022 724 <1> ; 09/05/2022 - Retro UNIX 386 v1.2 725 <1> ; 29/08/2020 - TRDOS 386 v2.0.2 726 <1> ; 04/02/2016 (ebx -> bx) 727 <1> ; 10/07/2015 728 <1> ; 14/01/2015 729 <1> ;push bx 730 0000028A 28FF <1> sub bh, bh 731 0000028C 8A1E[8962] <1> mov bl, [drv] 732 00000290 80FB80 <1> cmp bl, 80h 733 00000293 7203 <1> jb short sdp0 734 00000295 80EB7E <1> sub bl, 7Eh 735 <1> sdp0: 736 <1> ;add bx, drv.status 737 <1> ;mov byte [bx], 80h ; 'Present' flag 738 <1> ; 29/08/2020 739 00000298 C687[AE62]80 <1> mov byte [bx+drv.status], 80h 740 <1> ; 741 0000029D 88E8 <1> mov al, ch ; last cylinder (bits 0-7) 742 0000029F 88CC <1> mov ah, cl ; 743 000002A1 C0EC06 <1> shr ah, 6 ; last cylinder (bits 8-9) 744 <1> ;sub bx, drv.status 745 000002A4 D0E3 <1> shl bl, 1 746 <1> ;add bx, drv.cylinders 747 000002A6 40 <1> inc ax ; convert max. cyl number to cyl count 748 <1> ;mov [bx], ax 749 <1> ; 08/08/2022 750 <1> ; 29/08/2020 751 <1> ;mov [bx+drv.cylinders], ax 752 <1> ; 753 000002A7 50 <1> push ax ; ** cylinders 754 <1> ;sub bx, drv.cylinders 755 <1> ;add bx, drv.heads 756 000002A8 30E4 <1> xor ah, ah 757 000002AA 88F0 <1> mov al, dh ; heads 758 000002AC 40 <1> inc ax 759 <1> ;mov [bx], ax 760 <1> ; 08/08/2022 761 <1> ; 29/08/2020 762 <1> ;mov [bx+drv.heads], ax 763 <1> ;sub bx, drv.heads 764 <1> ;add bx, drv.spt 765 000002AD 30ED <1> xor ch, ch 766 000002AF 80E13F <1> and cl, 3Fh ; sectors (bits 0-6) 767 <1> ;mov [bx], cx 768 <1> ; 08/08/2022 769 <1> ; 29/08/2020 770 <1> ;mov [bx+drv.spt], cx 771 <1> ;sub bx, drv.spt 772 000002B2 D1E3 <1> shl bx, 1 773 <1> ;add bx, drv.size ; disk size (in sectors) 774 <1> ; LBA size = cylinders * heads * secpertrack 775 000002B4 F7E1 <1> mul cx 776 000002B6 89C2 <1> mov dx, ax ; heads*spt 777 000002B8 58 <1> pop ax ; ** cylinders 778 <1> ; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads) 779 <1> ;dec ax ; 1 cylinder reserved (!?) ; (*) 780 000002B9 F7E2 <1> mul dx ; cylinders * (heads*spt) 781 <1> ;mov [bx], ax 782 <1> ;mov [bx+2], dx 783 <1> ; 29/08/2020 784 000002BB 8987[9262] <1> mov [bx+drv.size], ax 785 000002BF 8997[9462] <1> mov [bx+drv.size+2], dx 786 <1> ; 787 <1> ;pop bx 788 000002C3 C3 <1> retn 789 <1> 790 <1> ;align 2 791 <1> 792 <1> ;cylinders : dw 0, 0, 0, 0, 0, 0 793 <1> ;heads : dw 0, 0, 0, 0, 0, 0 794 <1> ;spt : dw 0, 0, 0, 0, 0, 0 795 <1> ;disk_size : dd 0, 0, 0, 0, 0, 0 796 <1> 797 <1> ;last_drv: 798 <1> ; db 0 799 <1> ;drv_status: 800 <1> ; db 0,0,0,0,0,0 801 <1> ; db 0 802 <1> 803 <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015 804 <1> 805 <1> L16: 806 _L0: 807 ; 10/11/2014 808 000002C4 FA cli ; Disable interrupts (clear interrupt flag) 809 ; Reset Interrupt MASK Registers (Master&Slave) 810 ;mov al, 0FFh ; mask off all interrupts 811 ;out 21h, al ; on master PIC (8259) 812 ;jmp $+2 ; (delay) 813 ;out 0A1h, al ; on slave PIC (8259) 814 ; 815 ; Disable NMI 816 000002C5 B080 mov al, 80h 817 000002C7 E670 out 70h, al ; set bit 7 to 1 for disabling NMI 818 ; 23/02/2015 819 000002C9 90 nop ; 820 ;in al, 71h ; read in 71h just after writing out to 70h 821 ; for preventing unknown state (!?) 822 823 ; 01/01/2022 (Retro UNIX 386 v1.2) 824 %define KERNELFSIZE KEND-KSTART 825 ; 826 ; 20/08/2014 827 ; Moving the kernel 64 KB back (to physical address 0) 828 ; DS = CS = 1000h 829 ; 05/11/2014 830 000002CA 31C0 xor ax, ax 831 000002CC 8EC0 mov es, ax ; ES = 0 832 ; 833 ;;mov cx, (KEND - KLOAD)/4 834 ;mov cx, (KERNELFSIZE+3)/4 ; 01/01/2022 835 000002CE B97E32 mov cx, (KERNELFSIZE+1)/2 ; 02/01/2022 836 000002D1 31F6 xor si, si 837 000002D3 31FF xor di, di 838 ;rep movsd 839 000002D5 F3A5 rep movsw ; 02/01/2022 840 ; 841 000002D7 06 push es ; 0 842 000002D8 68[DC02] push L17 843 000002DB CB retf 844 ; 845 L17: 846 ; Turn off the floppy drive motor 847 000002DC BAF203 mov dx, 3F2h 848 000002DF EE out dx, al ; 0 ; 31/12/2013 849 850 ; Enable access to memory above one megabyte 851 L18: 852 000002E0 E464 in al, 64h 853 000002E2 A802 test al, 2 854 000002E4 75FA jnz short L18 855 000002E6 B0D1 mov al, 0D1h ; Write output port 856 000002E8 E664 out 64h, al 857 L19: 858 000002EA E464 in al, 64h 859 000002EC A802 test al, 2 860 000002EE 75FA jnz short L19 861 000002F0 B0DF mov al, 0DFh ; Enable A20 line 862 000002F2 E660 out 60h, al 863 ;L20: 864 ; 865 ; Load global descriptor table register 866 867 ;mov ax, cs 868 ;mov ds, ax 869 870 000002F4 2E0F0116[B05F] lgdt [cs:gdtd] 871 872 000002FA 0F20C0 mov eax, cr0 873 ;or eax, 1 874 000002FD 40 inc ax 875 000002FE 0F22C0 mov cr0, eax 876 877 ; Jump to 32 bit code 878 879 00000301 66 db 66h ; Prefix for 32-bit 880 00000302 EA db 0EAh ; Opcode for far jump 881 00000303 [09030000] dd StartPM ; Offset to start, 32-bit 882 ; (1000h:StartPM = StartPM + 10000h) 883 00000307 0800 dw KCODE ; This is the selector for CODE32_DESCRIPTOR, 884 ; assuming that StartPM resides in code32 885 886 [BITS 32] 887 888 StartPM: 889 ; Kernel Base Address = 0 ; 30/12/2013 890 00000309 66B81000 mov ax, KDATA ; Save data segment identifier 891 0000030D 8ED8 mov ds, ax ; Move a valid data segment into DS register 892 0000030F 8EC0 mov es, ax ; Move data segment into ES register 893 00000311 8EE0 mov fs, ax ; Move data segment into FS register 894 00000313 8EE8 mov gs, ax ; Move data segment into GS register 895 00000315 8ED0 mov ss, ax ; Move data segment into SS register 896 00000317 BC00000900 mov esp, 90000h ; Move the stack pointer to 090000h 897 898 clear_bss: ; Clear uninitialized data area 899 ; 11/03/2015 900 0000031C 31C0 xor eax, eax ; 0 901 ;mov ecx, (bss_end - bss_start)/4 902 ;;shr ecx, 2 ; bss section is already aligned for double words 903 ; 12/12/2021 904 0000031E B9B90C0000 mov ecx, BSS_SIZE/4 905 00000323 BF[00650000] mov edi, bss_start 906 00000328 F3AB rep stosd 907 908 memory_init: 909 ; Initialize memory allocation table and page tables 910 ; 911 ; 02/01/2022 (Retro UNIX 386 v1.2) 912 ; 16/11/2014 913 ; 15/11/2014 914 ; 07/11/2014 915 ; 06/11/2014 916 ; 05/11/2014 917 ; 04/11/2014 918 ; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 919 ; 920 ; xor eax, eax 921 ; xor ecx, ecx 922 0000032A B108 mov cl, 8 923 0000032C BF00001000 mov edi, MEM_ALLOC_TBL 924 00000331 F3AB rep stosd ; clear Memory Allocation Table 925 ; for the first 1 MB memory 926 ; 927 00000333 8B0D[F4640000] mov ecx, [mem_1m_1k] ; 02/01/2022 928 ;mov cx, [mem_1m_1k] ; Number of contiguous KB between 929 ; 1 and 16 MB, max. 3C00h = 15 MB. 930 ;shr cx, 2 ; convert 1 KB count to 4 KB count 931 00000339 C1E902 shr ecx, 2 ; 02/01/2022 932 0000033C 890D[70670000] mov [free_pages], ecx 933 00000342 8B15[F8640000] mov edx, [mem_16m_64k] ; 02/01/2022 934 ;mov dx, [mem_16m_64k] ; Number of contiguous 64 KB blocks 935 ; between 16 MB and 4 GB. 936 ;or dx, dx 937 00000348 09D2 or edx, edx ; 02/01/2022 938 0000034A 7412 jz short mi_0 939 ; 940 ;mov ax, dx 941 0000034C 89D0 mov eax, edx ; 02/01/2022 942 0000034E C1E004 shl eax, 4 ; 64 KB -> 4 KB (page count) 943 00000351 0105[70670000] add [free_pages], eax 944 00000357 0500100000 add eax, 4096 ; 16 MB = 4096 pages 945 0000035C EB06 jmp short mi_1 946 mi_0: 947 ;mov ax, cx 948 0000035E 89C8 mov eax, ecx ; 02/01/2022 949 00000360 66050001 add ax, 256 ; add 256 pages for the first 1 MB 950 mi_1: 951 00000364 A3[6C670000] mov [memory_size], eax ; Total available memory in pages 952 ; 1 alloc. tbl. bit = 1 memory page 953 ; 32 allocation bits = 32 mem. pages 954 ; 955 00000369 05FF7F0000 add eax, 32767 ; 32768 memory pages per 1 M.A.T. page 956 0000036E C1E80F shr eax, 15 ; ((32768 * x) + y) pages (y < 32768) 957 ; --> x + 1 M.A.T. pages, if y > 0 958 ; --> x M.A.T. pages, if y = 0 959 ;mov [mat_size], ax ; Memory Alloc. Table Size in pages 960 00000371 A3[80670000] mov [mat_size], eax ; 02/01/2022 961 00000376 C1E00C shl eax, 12 ; 1 M.A.T. page = 4096 bytes 962 ; ; Max. 32 M.A.T. pages (4 GB memory) 963 00000379 89C3 mov ebx, eax ; M.A.T. size in bytes 964 ; Set/Calculate Kernel's Page Directory Address 965 0000037B 81C300001000 add ebx, MEM_ALLOC_TBL 966 00000381 891D[68670000] mov [k_page_dir], ebx ; Kernel's Page Directory address 967 ; just after the last M.A.T. page 968 ; 969 00000387 83E804 sub eax, 4 ; convert M.A.T. size to offset value 970 0000038A A3[78670000] mov [last_page], eax ; last page ofset in the M.A.T. 971 ; ; (allocation status search must be 972 ; stopped after here) 973 0000038F 31C0 xor eax, eax 974 00000391 48 dec eax ; FFFFFFFFh (set all bits to 1) 975 ;push cx 976 00000392 51 push ecx ; 02/01/2022 977 00000393 C1E905 shr ecx, 5 ; convert 1 - 16 MB page count to 978 ; count of 32 allocation bits 979 00000396 F3AB rep stosd 980 ;pop cx 981 00000398 59 pop ecx ; 02/01/2022 982 00000399 40 inc eax ; 0 983 0000039A 80E11F and cl, 31 ; remain bits 984 0000039D 7412 jz short mi_4 985 0000039F 8907 mov [edi], eax ; reset 986 mi_2: 987 000003A1 0FAB07 bts [edi], eax ; 06/11/2014 988 000003A4 FEC9 dec cl 989 000003A6 7404 jz short mi_3 990 000003A8 FEC0 inc al 991 000003AA EBF5 jmp short mi_2 992 mi_3: 993 000003AC 28C0 sub al, al ; 0 994 000003AE 83C704 add edi, 4 ; 15/11/2014 995 mi_4: 996 000003B1 09D2 or edx, edx ; 02/01/2022 997 ;or dx, dx ; check 16M to 4G memory space 998 000003B3 741F jz short mi_6 ; max. 16 MB memory, no more... 999 ; 1000 000003B5 B900021000 mov ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory 1001 ; 1002 000003BA 29F9 sub ecx, edi ; displacement (to end of 16 MB) 1003 000003BC 7405 jz short mi_5 ; jump if EDI points to 1004 ; end of first 16 MB 1005 ;shr ecx, 1 ; convert to dword count 1006 ;shr ecx, 1 ; (shift 2 bits right) 1007 000003BE C1E902 shr ecx, 2 ; 02/01/2022 1008 000003C1 F3AB rep stosd ; reset all bits for reserved pages 1009 ; (memory hole under 16 MB) 1010 mi_5: 1011 000003C3 89D1 mov ecx, edx ; 02/01/2022 1012 ;mov cx, dx ; count of 64 KB memory blocks 1013 000003C5 D1E9 shr ecx, 1 ; 1 alloc. dword per 128 KB memory 1014 000003C7 9C pushf ; 16/11/2014 1015 000003C8 48 dec eax ; FFFFFFFFh (set all bits to 1) 1016 000003C9 F3AB rep stosd 1017 000003CB 40 inc eax ; 0 1018 000003CC 9D popf ; 16/11/2014 1019 000003CD 7305 jnc short mi_6 1020 000003CF 6648 dec ax ; eax = 0000FFFFh 1021 000003D1 AB stosd 1022 000003D2 6640 inc ax ; 0 1023 mi_6: 1024 000003D4 39DF cmp edi, ebx ; check if EDI points to 1025 000003D6 7309 jnb short mi_7 ; end of memory allocation table 1026 ; ; (>= MEM_ALLOC_TBL + 4906) 1027 000003D8 89D9 mov ecx, ebx ; end of memory allocation table 1028 000003DA 29F9 sub ecx, edi ; convert displacement/offset 1029 ;shr ecx, 1 ; to dword count 1030 ;shr ecx, 1 ; (shift 2 bits right) 1031 000003DC C1E902 shr ecx, 2 ; 02/01/2022 1032 000003DF F3AB rep stosd ; reset all remain M.A.T. bits 1033 mi_7: 1034 ; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages) 1035 000003E1 BA00001000 mov edx, MEM_ALLOC_TBL 1036 ;sub ebx, edx ; Mem. Alloc. Tbl. size in bytes 1037 ;shr ebx, 12 ; Mem. Alloc. Tbl. size in pages 1038 000003E6 8B0D[80670000] mov ecx, [mat_size] ; 02/01/2022 1039 ;mov cx, [mat_size] ; Mem. Alloc. Tbl. size in pages 1040 000003EC 89D7 mov edi, edx 1041 000003EE C1EF0F shr edi, 15 ; convert M.A.T. address to 1042 ; byte offset in M.A.T. 1043 ; (1 M.A.T. byte points to 1044 ; 32768 bytes) 1045 ; Note: MEM_ALLOC_TBL address 1046 ; must be aligned on 128 KB 1047 ; boundary! 1048 000003F1 01D7 add edi, edx ; points to M.A.T.'s itself 1049 ; eax = 0 1050 000003F3 290D[70670000] sub [free_pages], ecx ; 07/11/2014 1051 mi_8: 1052 000003F9 0FB307 btr [edi], eax ; clear bit 0 to bit x (1 to 31) 1053 ;dec bl 1054 000003FC FEC9 dec cl 1055 000003FE 7404 jz short mi_9 1056 00000400 FEC0 inc al 1057 00000402 EBF5 jmp short mi_8 1058 mi_9: 1059 ; 1060 ; Reset Kernel's Page Dir. and Page Table bits in M.A.T. 1061 ; (allocate pages for system page tables) 1062 1063 ; edx = MEM_ALLOC_TBL 1064 00000404 8B0D[6C670000] mov ecx, [memory_size] ; memory size in pages (PTEs) 1065 0000040A 81C1FF030000 add ecx, 1023 ; round up (1024 PTEs per table) 1066 00000410 C1E90A shr ecx, 10 ; convert memory page count to 1067 ; page table count (PDE count) 1068 ; 1069 00000413 51 push ecx ; (**) PDE count (<= 1024) 1070 ; 1071 00000414 41 inc ecx ; +1 for kernel page directory 1072 ; 1073 00000415 290D[70670000] sub [free_pages], ecx ; 07/11/2014 1074 ; 1075 0000041B 8B35[68670000] mov esi, [k_page_dir] ; Kernel's Page Directory address 1076 00000421 C1EE0C shr esi, 12 ; convert to page number 1077 mi_10: 1078 00000424 89F0 mov eax, esi ; allocation bit offset 1079 00000426 89C3 mov ebx, eax 1080 00000428 C1EB03 shr ebx, 3 ; convert to alloc. byte offset 1081 0000042B 80E3FC and bl, 0FCh ; clear bit 0 and bit 1 1082 ; to align on dword boundary 1083 0000042E 83E01F and eax, 31 ; set allocation bit position 1084 ; (bit 0 to bit 31) 1085 ; 1086 00000431 01D3 add ebx, edx ; offset in M.A.T. + M.A.T. address 1087 ; 1088 00000433 0FB303 btr [ebx], eax ; reset relevant bit (0 to 31) 1089 ; 1090 00000436 46 inc esi ; next page table 1091 00000437 E2EB loop mi_10 ; allocate next kernel page table 1092 ; (ecx = page table count + 1) 1093 ; 1094 00000439 59 pop ecx ; (**) PDE count (= pg. tbl. count) 1095 ; 1096 ; Initialize Kernel Page Directory and Kernel Page Tables 1097 ; 1098 ; Initialize Kernel's Page Directory 1099 0000043A 8B3D[68670000] mov edi, [k_page_dir] 1100 00000440 89F8 mov eax, edi 1101 00000442 0C03 or al, PDE_A_PRESENT + PDE_A_WRITE 1102 ; supervisor + read&write + present 1103 00000444 89CA mov edx, ecx ; (**) PDE count (= pg. tbl. count) 1104 mi_11: 1105 00000446 0500100000 add eax, 4096 ; Add page size (PGSZ) 1106 ; EAX points to next page table 1107 0000044B AB stosd 1108 0000044C E2F8 loop mi_11 1109 0000044E 29C0 sub eax, eax ; Empty PDE 1110 ;mov cx, 1024 ; Entry count (PGSZ/4) 1111 ; 02/01/2022 1112 00000450 B504 mov ch, 4 ; cx = 4*256 = 1024 1113 00000452 29D1 sub ecx, edx 1114 00000454 7402 jz short mi_12 1115 00000456 F3AB rep stosd ; clear remain (empty) PDEs 1116 ; 1117 ; Initialization of Kernel's Page Directory is OK, here. 1118 mi_12: 1119 ; Initialize Kernel's Page Tables 1120 ; 1121 ; (EDI points to address of page table 0) 1122 ; eax = 0 1123 00000458 8B0D[6C670000] mov ecx, [memory_size] ; memory size in pages 1124 0000045E 89CA mov edx, ecx ; (***) 1125 00000460 B003 mov al, PTE_A_PRESENT + PTE_A_WRITE 1126 ; supervisor + read&write + present 1127 mi_13: 1128 00000462 AB stosd 1129 00000463 0500100000 add eax, 4096 1130 00000468 E2F8 loop mi_13 1131 ; 02/01/2022 1132 0000046A 66B9FF03 mov cx, 1023 1133 0000046E 21CA and edx, ecx 1134 ;and dx, 1023 ; (***) 1135 00000470 7407 jz short mi_14 1136 ;mov cx, 1024 1137 ; 02/01/2022 1138 ;mov ch, 4 ; cx = 4*256 = 1024 1139 00000472 41 inc ecx ; ecx = 1024 1140 00000473 29D1 sub ecx, edx 1141 ;sub cx, dx ; from dx (<= 1023) to 1024 1142 00000475 31C0 xor eax, eax 1143 00000477 F3AB rep stosd ; clear remain (empty) PTEs 1144 ; of the last page table 1145 mi_14: 1146 ; Initialization of Kernel's Page Tables is OK, here. 1147 ; 1148 00000479 89F8 mov eax, edi ; end of the last page table page 1149 ; (beginging of user space pages) 1150 0000047B C1E80F shr eax, 15 ; convert to M.A.T. byte offset 1151 0000047E 24FC and al, 0FCh ; clear bit 0 and bit 1 for 1152 ; aligning on dword boundary 1153 1154 00000480 A3[7C670000] mov [first_page], eax 1155 00000485 A3[74670000] mov [next_page], eax ; The first free page pointer 1156 ; for user programs 1157 ; (Offset in Mem. Alloc. Tbl.) 1158 ; 1159 ; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here. 1160 ; 1161 1162 ; Enable paging 1163 ; 1164 0000048A A1[68670000] mov eax, [k_page_dir] 1165 0000048F 0F22D8 mov cr3, eax 1166 00000492 0F20C0 mov eax, cr0 1167 00000495 0D00000080 or eax, 80000000h ; set paging bit (bit 31) 1168 0000049A 0F22C0 mov cr0, eax 1169 ;jmp KCODE:StartPMP 1170 1171 0000049D EA db 0EAh ; Opcode for far jump 1172 0000049E [A4040000] dd StartPMP ; 32 bit offset 1173 000004A2 0800 dw KCODE ; kernel code segment descriptor 1174 1175 StartPMP: 1176 ; 06/11//2014 1177 ; Clear video page 0 1178 ; 1179 ; Temporary Code 1180 ; 1181 ;mov ecx, 80*25/2 1182 000004A4 66B9E803 mov cx, (80*25)/2 ; 02/01/2022 1183 000004A8 BF00800B00 mov edi, 0B8000h 1184 000004AD 57 push edi ; * ; 02/01/2022 1185 000004AE 31C0 xor eax, eax ; black background, black fore color 1186 000004B0 F3AB rep stosd 1187 1188 ; 19/08/2014 1189 ; Kernel Base Address = 0 1190 ; It is mapped to (physically) 0 in the page table. 1191 ; So, here is exactly 'StartPMP' address. 1192 ; 1193 ;;mov ah, 4Eh ; Red background, yellow forecolor 1194 ;;mov esi, msgPM 1195 ;; 14/08/2015 (kernel version message will appear 1196 ;; when protected mode and paging is enabled) 1197 000004B2 B40B mov ah, 0Bh ; Black background, light cyan forecolor 1198 000004B4 BE[C4620000] mov esi, msgKVER 1199 000004B9 5F pop edi ; * ; 02/01/2022 1200 ;mov edi, 0B8000h ; 27/08/2014 1201 ; 20/08/2014 1202 000004BA E88F010000 call printk 1203 1204 ; 'UNIX v7/x86' source code by Robert Nordier (1999) 1205 ; // Set IRQ offsets 1206 ; 1207 ; Linux (v0.12) source code by Linus Torvalds (1991) 1208 ; 1209 ;; ICW1 1210 000004BF B011 mov al, 11h ; Initialization sequence 1211 000004C1 E620 out 20h, al ; 8259A-1 1212 ; jmp $+2 1213 000004C3 E6A0 out 0A0h, al ; 8259A-2 1214 ;; ICW2 1215 000004C5 B020 mov al, 20h ; Start of hardware ints (20h) 1216 000004C7 E621 out 21h, al ; for 8259A-1 1217 ; jmp $+2 1218 000004C9 B028 mov al, 28h ; Start of hardware ints (28h) 1219 000004CB E6A1 out 0A1h, al ; for 8259A-2 1220 ; 1221 000004CD B004 mov al, 04h ;; ICW3 1222 000004CF E621 out 21h, al ; IRQ2 of 8259A-1 (master) 1223 ; jmp $+2 1224 000004D1 B002 mov al, 02h ; is 8259A-2 (slave) 1225 000004D3 E6A1 out 0A1h, al ; 1226 ;; ICW4 1227 000004D5 B001 mov al, 01h ; 1228 000004D7 E621 out 21h, al ; 8086 mode, normal EOI 1229 ; jmp $+2 1230 000004D9 E6A1 out 0A1h, al ; for both chips. 1231 1232 ;mov al, 0FFh ; mask off all interrupts for now 1233 ;out 21h, al 1234 ;; jmp $+2 1235 ;out 0A1h, al 1236 1237 ; 02/04/2015 1238 ; 26/03/2015 System call (INT 30h) modification 1239 ; DPL = 3 (Interrupt service routine can be called from user mode) 1240 ; 1241 ;; Linux (v0.12) source code by Linus Torvalds (1991) 1242 ; setup_idt: 1243 ; 1244 ;; 16/02/2015 1245 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 1246 ; 21/08/2014 (timer_int) 1247 000004DB BE[BC5F0000] mov esi, ilist 1248 000004E0 8D3D[00650000] lea edi, [idt] 1249 ; 26/03/2015 1250 ;mov ecx, 48 ; 48 hardware interrupts (INT 0 to INT 2Fh) 1251 ; 02/01/2022 1252 000004E6 B130 mov cl, 48 ; ecx = 48 1253 ; 02/04/2015 1254 000004E8 BB00000800 mov ebx, 80000h 1255 rp_sidt1: 1256 000004ED AD lodsd 1257 000004EE 89C2 mov edx, eax 1258 000004F0 66BA008E mov dx, 8E00h 1259 000004F4 6689C3 mov bx, ax 1260 000004F7 89D8 mov eax, ebx ; /* selector = 0x0008 = cs */ 1261 ; /* interrupt gate - dpl=0, present */ 1262 000004F9 AB stosd ; selector & offset bits 0-15 1263 000004FA 89D0 mov eax, edx 1264 000004FC AB stosd ; attributes & offset bits 16-23 1265 000004FD E2EE loop rp_sidt1 1266 000004FF B110 mov cl, 16 ; 16 software interrupts (INT 30h to INT 3Fh) 1267 rp_sidt2: 1268 00000501 AD lodsd 1269 00000502 21C0 and eax, eax 1270 00000504 7413 jz short rp_sidt3 1271 00000506 89C2 mov edx, eax 1272 00000508 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 1273 0000050C 6689C3 mov bx, ax 1274 0000050F 89D8 mov eax, ebx ; selector & offset bits 0-15 1275 00000511 AB stosd 1276 00000512 89D0 mov eax, edx 1277 00000514 AB stosd 1278 00000515 E2EA loop rp_sidt2 1279 00000517 EB16 jmp short sidt_OK 1280 rp_sidt3: 1281 00000519 B8[72090000] mov eax, ignore_int 1282 0000051E 89C2 mov edx, eax 1283 00000520 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 1284 00000524 6689C3 mov bx, ax 1285 00000527 89D8 mov eax, ebx ; selector & offset bits 0-15 1286 rp_sidt4: 1287 00000529 AB stosd 1288 0000052A 92 xchg eax, edx 1289 0000052B AB stosd 1290 0000052C 92 xchg edx, eax 1291 0000052D E2FA loop rp_sidt4 1292 sidt_OK: 1293 0000052F 0F011D[B65F0000] lidt [idtd] 1294 ; 1295 ; TSS descriptor setup ; 24/03/2015 1296 00000536 B8[00670000] mov eax, task_state_segment 1297 0000053B 66A3[AA5F0000] mov [gdt_tss0], ax 1298 00000541 C1C010 rol eax, 16 1299 00000544 A2[AC5F0000] mov [gdt_tss1], al 1300 00000549 8825[AF5F0000] mov [gdt_tss2], ah 1301 0000054F 66C705[66670000]68- mov word [tss.IOPB], tss_end - task_state_segment 1302 00000557 00 1303 ; 1304 ; IO Map Base address (When this address points 1305 ; to end of the TSS, CPU does not use IO port 1306 ; permission bit map for RING 3 IO permissions, 1307 ; access to any IO ports in ring 3 will be forbidden.) 1308 ; 1309 ;mov [tss.esp0], esp ; TSS offset 4 1310 ;mov word [tss.ss0], KDATA ; TSS offset 8 (SS) 1311 00000558 66B82800 mov ax, TSS ; It is needed when an interrupt 1312 ; occurs (or a system call -software INT- is requested) 1313 ; while cpu running in ring 3 (in user mode). 1314 ; (Kernel stack pointer and segment will be loaded 1315 ; from offset 4 and 8 of the TSS, by the CPU.) 1316 0000055C 0F00D8 ltr ax ; Load task register 1317 ; 1318 esp0_set0: 1319 ; 30/07/2015 1320 0000055F 8B0D[6C670000] mov ecx, [memory_size] ; memory size in pages 1321 00000565 C1E10C shl ecx, 12 ; convert page count to byte count 1322 00000568 81F900004000 cmp ecx, CORE ; beginning of user's memory space (400000h) 1323 ; (kernel mode virtual address) 1324 0000056E 7605 jna short esp0_set1 1325 ; 1326 ; If available memory > CORE (end of the 1st 4 MB) 1327 ; set stack pointer to CORE 1328 ;(Because, PDE 0 is reserved for kernel space in user's page directory) 1329 ;(PDE 0 points to page table of the 1st 4 MB virtual address space) 1330 00000570 B900004000 mov ecx, CORE 1331 esp0_set1: 1332 00000575 89CC mov esp, ecx ; top of kernel stack (**tss.esp0**) 1333 esp0_set_ok: 1334 ; 30/07/2015 (**tss.esp0**) 1335 00000577 8925[04670000] mov [tss.esp0], esp 1336 0000057D 66C705[08670000]10- mov word [tss.ss0], KDATA 1337 00000585 00 1338 ; 14/08/2015 1339 ; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan) 1340 ; 1341 ;cli ; Disable interrupts (for CPU) 1342 ; (CPU will not handle hardware interrupts, except NMI!) 1343 ; 1344 00000586 30C0 xor al, al ; Enable all hardware interrupts! 1345 00000588 E621 out 21h, al ; (IBM PC-AT compatibility) 1346 0000058A EB00 jmp $+2 ; (All conventional PC-AT hardware 1347 0000058C E6A1 out 0A1h, al ; interrupts will be in use.) 1348 ; (Even if related hardware component 1349 ; does not exist!) 1350 ; Enable NMI 1351 0000058E B07F mov al, 7Fh ; Clear bit 7 to enable NMI (again) 1352 00000590 E670 out 70h, al 1353 ; 23/02/2015 1354 00000592 90 nop 1355 00000593 E471 in al, 71h ; read in 71h just after writing out to 70h 1356 ; for preventing unknown state (!?) 1357 ; 1358 ; Only a NMI can occur here... (Before a 'STI' instruction) 1359 ; 1360 ; 02/09/2014 1361 00000595 6631DB xor bx, bx 1362 00000598 66BA0002 mov dx, 0200h ; Row 2, column 0 ; 07/03/2015 1363 0000059C E81D0E0000 call set_cpos 1364 ; 1365 ; 06/11/2014 1366 ; Temporary Code 1367 ; 1368 000005A1 E8920F0000 call memory_info 1369 ; 14/08/2015 1370 ;call getch ; 28/02/2015 1371 drv_init: 1372 000005A6 FB sti ; Enable Interrupts 1373 ; 06/02/2015 1374 000005A7 8B15[8E620000] mov edx, [hd0_type] ; hd0, hd1, hd2, hd3 1375 000005AD 668B1D[8C620000] mov bx, [fd0_type] ; fd0, fd1 1376 ; 22/02/2015 1377 000005B4 6621DB and bx, bx 1378 000005B7 751B jnz short di1 1379 ; 1380 000005B9 09D2 or edx, edx 1381 000005BB 7529 jnz short di2 1382 ; 1383 setup_error: 1384 000005BD BE[AD630000] mov esi, setup_error_msg 1385 psem: 1386 000005C2 AC lodsb 1387 000005C3 08C0 or al, al 1388 ;jz short haltx ; 22/02/2015 1389 000005C5 7426 jz short di3 1390 000005C7 56 push esi 1391 000005C8 31DB xor ebx, ebx ; 0 1392 ; Video page 0 (bl=0) 1393 000005CA B407 mov ah, 07h ; Black background, 1394 ; light gray forecolor 1395 000005CC E8E30C0000 call write_tty 1396 000005D1 5E pop esi 1397 000005D2 EBEE jmp short psem 1398 1399 di1: 1400 ; supress 'jmp short T6' 1401 ; (activate fdc motor control code) 1402 000005D4 66C705[CF060000]90- mov word [T5], 9090h ; nop 1403 000005DC 90 1404 ; 1405 ;mov ax, int_0Eh ; IRQ 6 handler 1406 ;mov di, 0Eh*4 ; IRQ 6 vector 1407 ;stosw 1408 ;mov ax, cs 1409 ;stosw 1410 ;; 16/02/2015 1411 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 1412 ; 1413 000005DD E8FC180000 CALL DSKETTE_SETUP ; Initialize Floppy Disks 1414 ; 1415 000005E2 09D2 or edx, edx 1416 000005E4 7407 jz short di3 1417 di2: 1418 000005E6 E825190000 call DISK_SETUP ; Initialize Fixed Disks 1419 000005EB 72D0 jc short setup_error 1420 di3: 1421 000005ED E81A0F0000 call setup_rtc_int ; 22/05/2015 (dsectrpm.s) 1422 ; 1423 000005F2 E8DD580000 call display_disks ; 07/03/2015 (Temporary) 1424 ;haltx: 1425 ; 14/08/2015 1426 ;call getch ; 22/02/2015 1427 000005F7 FB sti ; Enable interrupts (for CPU) 1428 ; 14/08/2015 1429 ;mov ecx, 0FFFFFFFh 1430 ; 22/11/2021 1431 000005F8 B9FFFF2F00 mov ecx, 02FFFFFh 1432 md_info_msg_wait: 1433 000005FD 51 push ecx 1434 000005FE B001 mov al, 1 1435 00000600 8A25[96670000] mov ah, [ptty] ; active (current) video page 1436 00000606 E864550000 call getc_n 1437 0000060B 59 pop ecx 1438 0000060C 7502 jnz short md_info_msg_ok 1439 0000060E E2ED loop md_info_msg_wait 1440 md_info_msg_ok: 1441 ; 30/06/2015 1442 00000610 E8BF220000 call sys_init 1443 ; 1444 ;jmp cpu_reset ; 22/02/2015 1445 hang: 1446 ; 04/12/2021 1447 00000615 29C0 sub eax, eax 1448 _hang: 1449 ; 23/02/2015 1450 ;sti ; Enable interrupts 1451 00000617 F4 hlt 1452 ; 1453 ;nop 1454 ;; 03/12/2014 1455 ;; 28/08/2014 1456 ;mov ah, 11h 1457 ;call getc 1458 ;jz _c8 1459 ; 1460 ; 23/02/2015 1461 ; 06/02/2015 1462 ; 07/09/2014 1463 00000618 31DB xor ebx, ebx 1464 0000061A 8A1D[96670000] mov bl, [ptty] ; active_page 1465 00000620 89DE mov esi, ebx 1466 ;shl si, 1 1467 ; 17/07/2022 1468 00000622 D1E6 shl esi, 1 1469 00000624 81C6[98670000] add esi, ttychr 1470 0000062A 668B06 mov ax, [esi] 1471 ;and ax, ax 1472 ;;jz short _c8 1473 ;jz short hang 1474 ; 04/12/2021 1475 0000062D 21C0 and eax, eax 1476 0000062F 74E6 jz short _hang 1477 00000631 66C7060000 mov word [esi], 0 1478 00000636 80FB03 cmp bl, 3 ; Video page 3 1479 ;jb short _c8 1480 00000639 72DA jb short hang 1481 ; 1482 ; 02/09/2014 1483 0000063B B40E mov ah, 0Eh ; Yellow character 1484 ; on black background 1485 ; 30/11/2021 (32 bit reg push-pop) 1486 ; 07/09/2014 1487 nxtl: 1488 0000063D 53 push ebx 1489 ; 1490 ;xor ebx, ebx ; bl = 0 (video page 0) 1491 ; bh = 0 (video mode) 1492 ; Retro UNIX 386 v1 - Video Mode 0 1493 ; (PC/AT Video Mode 3 - 80x25 Alpha.) 1494 0000063E 50 push eax 1495 0000063F E8700C0000 call write_tty 1496 00000644 58 pop eax 1497 ;pop bx 1498 00000645 5B pop ebx 1499 00000646 3C0D cmp al, 0Dh ; carriage return (enter) 1500 ;jne short _c8 1501 00000648 75CB jne short hang 1502 0000064A B00A mov al, 0Ah ; next line 1503 0000064C EBEF jmp short nxtl 1504 1505 ;_c8: 1506 ; ; 25/08/2014 1507 ; cli ; Disable interrupts 1508 ; mov al, [scounter + 1] 1509 ; and al, al 1510 ; jnz hang 1511 ; call rtc_p 1512 ; jmp hang 1513 1514 1515 ; 27/08/2014 1516 ; 20/08/2014 1517 printk: 1518 ;mov edi, [scr_row] 1519 pkl: 1520 0000064E AC lodsb 1521 0000064F 08C0 or al, al 1522 00000651 7404 jz short pkr 1523 00000653 66AB stosw 1524 00000655 EBF7 jmp short pkl 1525 pkr: 1526 00000657 C3 retn 1527 1528 ; 25/07/2015 1529 ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer) 1530 ; 17/02/2015 1531 ; 06/02/2015 (unix386.s) 1532 ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 1533 ; 1534 ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85) 1535 ; 1536 ;-- HARDWARE INT 08 H - ( IRQ LEVEL 0 ) --------------------------------------- 1537 ; THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF : 1538 ; THE 8254 TIMER. INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR : 1539 ; IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND. : 1540 ; : 1541 ; THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE : 1542 ; POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY. : 1543 ; THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40) : 1544 ; OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE : 1545 ; DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS. : 1546 ; THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH : 1547 ; INTERRUPT 1CH AT EVERY TIME TICK. THE USER MUST CODE A : 1548 ; ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE. : 1549 ;------------------------------------------------------------------------------- 1550 ; 1551 1552 timer_int: ; IRQ 0 1553 ;int_08h: ; Timer 1554 ; 14/10/2015 1555 ; Here, we are simulating system call entry (for task switch) 1556 ; (If multitasking is enabled, 1557 ; 'clock' procedure may jump to 'sysrelease') 1558 00000658 1E push ds 1559 00000659 06 push es 1560 0000065A 0FA0 push fs 1561 0000065C 0FA8 push gs 1562 0000065E 60 pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 1563 0000065F 66B91000 mov cx, KDATA 1564 00000663 8ED9 mov ds, cx 1565 00000665 8EC1 mov es, cx 1566 00000667 8EE1 mov fs, cx 1567 00000669 8EE9 mov gs, cx 1568 ; 1569 0000066B 0F20D9 mov ecx, cr3 1570 0000066E 890D[11070000] mov [cr3reg], ecx ; save current cr3 register value/content 1571 ; 1572 00000674 3B0D[68670000] cmp ecx, [k_page_dir] 1573 0000067A 741F je short T3 1574 ; 1575 ; timer interrupt has been occurred while OS is in user mode 1576 0000067C A3[A46C0000] mov [u.r0], eax 1577 00000681 89E1 mov ecx, esp 1578 00000683 83C130 add ecx, ESPACE ; 4 * 12 (stack frame) 1579 00000686 890D[9C6C0000] mov [u.sp], ecx ; kernel stack pointer at the start of interrupt 1580 0000068C 8925[A06C0000] mov [u.usp], esp ; kernel stack points to user's registers 1581 ; 1582 00000692 8B0D[68670000] mov ecx, [k_page_dir] 1583 00000698 0F22D9 mov cr3, ecx 1584 T3: 1585 0000069B FB sti ; INTERRUPTS BACK ON 1586 0000069C 66FF05[E4670000] INC word [TIMER_LOW] ; INCREMENT TIME 1587 000006A3 7507 JNZ short T4 ; GO TO TEST_DAY 1588 000006A5 66FF05[E6670000] INC word [TIMER_HIGH] ; INCREMENT HIGH WORD OF TIME 1589 T4: ; TEST_DAY 1590 000006AC 66833D[E6670000]18 CMP word [TIMER_HIGH],018H ; TEST FOR COUNT EQUALING 24 HOURS 1591 000006B4 7519 JNZ short T5 ; GO TO DISKETTE_CTL 1592 000006B6 66813D[E4670000]B0- CMP word [TIMER_LOW],0B0H 1593 000006BE 00 1594 000006BF 750E JNZ short T5 ; GO TO DISKETTE_CTL 1595 1596 ;----- TIMER HAS GONE 24 HOURS 1597 ;;SUB AX,AX 1598 ;MOV [TIMER_HIGH],AX 1599 ;MOV [TIMER_LOW],AX 1600 000006C1 29C0 sub eax, eax 1601 000006C3 A3[E4670000] mov [TIMER_LH], eax 1602 ; 1603 000006C8 C605[E8670000]01 MOV byte [TIMER_OFL],1 1604 1605 ;----- TEST FOR DISKETTE TIME OUT 1606 1607 T5: 1608 ; 23/12/2014 1609 000006CF EB1D jmp short T6 ; will be replaced with nop, nop 1610 ; (9090h) if a floppy disk 1611 ; is detected. 1612 ;mov al,[CS:MOTOR_COUNT] 1613 000006D1 A0[EB670000] mov al, [MOTOR_COUNT] 1614 000006D6 FEC8 dec al 1615 ;mov [CS:MOTOR_COUNT], al ; DECREMENT DISKETTE MOTOR CONTROL 1616 000006D8 A2[EB670000] mov [MOTOR_COUNT], al 1617 ;mov [ORG_MOTOR_COUNT], al 1618 000006DD 750F JNZ short T6 ; RETURN IF COUNT NOT OUT 1619 000006DF B0F0 mov al,0F0h 1620 ;AND [CS:MOTOR_STATUS],al ; TURN OFF MOTOR RUNNING BITS 1621 000006E1 2005[EA670000] and [MOTOR_STATUS], al 1622 ;and [ORG_MOTOR_STATUS], al 1623 000006E7 B00C MOV AL,0CH ; bit 3 = enable IRQ & DMA, 1624 ; bit 2 = enable controller 1625 ; 1 = normal operation 1626 ; 0 = reset 1627 ; bit 0, 1 = drive select 1628 ; bit 4-7 = motor running bits 1629 000006E9 66BAF203 MOV DX,03F2H ; FDC CTL PORT 1630 000006ED EE OUT DX,AL ; TURN OFF THE MOTOR 1631 T6: 1632 ;inc word [CS:wait_count] ; 22/12/2014 (byte -> word) 1633 ; TIMER TICK INTERRUPT 1634 ;;inc word [wait_count] ;;27/02/2015 1635 ;INT 1CH ; TRANSFER CONTROL TO A USER ROUTINE 1636 ;;;;cli 1637 ;call u_timer ; TRANSFER CONTROL TO A USER ROUTINE 1638 000006EE FF15[09070000] call [x_timer] ; 14/05/2015 1639 T7: 1640 ; 14/10/2015 1641 000006F4 B020 MOV AL,EOI ; GET END OF INTERRUPT MASK 1642 000006F6 FA CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 1643 000006F7 E620 OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 1644 ; 1645 000006F9 A1[11070000] mov eax, [cr3reg] ; previous value/content of cr3 register 1646 000006FE 0F22D8 mov cr3, eax ; restore cr3 register content 1647 ; 1648 00000701 61 popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 1649 ; 1650 00000702 0FA9 pop gs 1651 00000704 0FA1 pop fs 1652 00000706 07 pop es 1653 00000707 1F pop ds 1654 00000708 CF iretd ; return from interrupt 1655 1656 1657 ; //////////////// 1658 1659 ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt) 1660 x_timer: 1661 00000709 [15070000] dd u_timer ; (temporary demo code) ; 14/05/2015 1662 ;dd clock 1663 1664 ; 23/02/2022 - Real time clock (digital) output demo (sys emt) 1665 x_rtci: 1666 0000070D [4B0A0000] dd rtc_p ; (temporary demo code) ; 23/02/2022 1667 1668 ; 14/10/2015 1669 00000711 00000000 cr3reg: dd 0 1670 1671 ; 04/12/2021 - Retro UNIX 386 v1.2 1672 ; 06/02/2015 1673 ; 07/09/2014 1674 ; 21/08/2014 1675 u_timer: 1676 ;timer_int: ; IRQ 0 1677 ; 06/02/2015 1678 ;push eax 1679 ;push edx 1680 ;push ecx 1681 ;push ebx 1682 ;push ds 1683 ;push es 1684 ;mov eax, KDATA 1685 ;mov ds, ax 1686 ;mov es, ax 1687 00000715 FF05[AC670000] inc dword [tcount] 1688 0000071B BB[36630000] mov ebx, tcountstr + 4 1689 ;mov ax, [tcount] 1690 ; 04/12/2021 1691 00000720 A1[AC670000] mov eax, [tcount] 1692 00000725 B90A000000 mov ecx, 10 1693 rp_divtcnt: 1694 0000072A 31D2 xor edx, edx 1695 0000072C F7F1 div ecx 1696 0000072E 80C230 add dl, 30h 1697 00000731 8813 mov [ebx], dl 1698 ;or ax, ax 1699 ; 04/12/2021 1700 00000733 09C0 or eax, eax 1701 00000735 7403 jz short print_lzero 1702 00000737 4B dec ebx 1703 00000738 EBF0 jmp short rp_divtcnt 1704 print_lzero: 1705 0000073A 81FB[32630000] cmp ebx, tcountstr 1706 00000740 7606 jna short print_tcount 1707 00000742 4B dec ebx 1708 00000743 C60330 mov byte [ebx], 30h 1709 00000746 EBF2 jmp short print_lzero 1710 print_tcount: 1711 00000748 56 push esi 1712 00000749 57 push edi 1713 0000074A BE[0E630000] mov esi, timer_msg ; Timer interrupt message 1714 ; 07/09/2014 1715 ;mov bx, 1 ; Video page 1 1716 ; 04/12/2021 1717 0000074F 29DB sub ebx, ebx 1718 ;inc bl ; ebx = 1 1719 ; 02/01/2022 1720 00000751 B306 mov bl, 6 ; Video page 6 1721 ptmsg: 1722 00000753 AC lodsb 1723 00000754 08C0 or al, al 1724 00000756 740D jz short ptmsg_ok 1725 00000758 56 push esi 1726 ;push bx 1727 ; 04/12/2021 1728 00000759 53 push ebx 1729 0000075A B42F mov ah, 2Fh ; Green background, white forecolor 1730 0000075C E8530B0000 call write_tty 1731 ;pop bx 1732 ; 04/12/2021 1733 00000761 5B pop ebx 1734 00000762 5E pop esi 1735 00000763 EBEE jmp short ptmsg 1736 ;; 27/08/2014 1737 ;mov edi, 0B8000h + 0A0h ; Row 1 1738 ;call printk 1739 ; 1740 ptmsg_ok: 1741 ; 07/09/2014 1742 ;xor dx, dx ; column 0, row 0 1743 ; 04/12/2021 1744 00000765 31D2 xor edx, edx 1745 00000767 E8520C0000 call set_cpos ; set cursor position to 0,0 1746 ; 23/02/2015 1747 ; 25/08/2014 1748 ;mov ebx, scounter ; (seconds counter) 1749 ;dec byte [ebx+1] ; (for reading real time clock) 1750 ; dec byte [scounter+1] 1751 ;; jns short timer_eoi ; 0 -> 0FFh ? 1752 ; jns short u_timer_retn 1753 ; 26/02/2015 1754 ; call rtc_p 1755 ; mov ebx, scounter ; (seconds counter) 1756 ; mov byte [ebx+1], 18 ; (18.2 timer ticks per second) 1757 ; dec byte [ebx] ; 19+18+18+18+18 (5) 1758 ; jnz short timer_eoi ; (109 timer ticks in 5 seconds) 1759 ; jnz short u_timer_retn ; 06/02/2015 1760 ; mov byte [ebx], 5 1761 ; inc byte [ebx+1] ; 19 1762 ;;timer_eoi: 1763 ;; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1764 ;; out 20h, al ; 8259 PORT 1765 ; 1766 ;u_timer_retn: ; 06/02/2015 1767 0000076C 5F pop edi 1768 0000076D 5E pop esi 1769 ;pop es 1770 ;pop ds 1771 ;pop ebx 1772 ;pop ecx 1773 ;pop edx 1774 ;pop eax 1775 ;iret 1776 0000076E C3 retn ; 06/02/2015 1777 1778 ; 28/08/2014 1779 irq0: 1780 0000076F 6A00 push dword 0 1781 00000771 EB48 jmp short which_irq 1782 irq1: 1783 00000773 6A01 push dword 1 1784 00000775 EB44 jmp short which_irq 1785 irq2: 1786 00000777 6A02 push dword 2 1787 00000779 EB40 jmp short which_irq 1788 irq3: 1789 ; 20/11/2015 1790 ; 24/10/2015 1791 0000077B 2EFF15[58300000] call dword [cs:com2_irq3] 1792 00000782 6A03 push dword 3 1793 00000784 EB35 jmp short which_irq 1794 irq4: 1795 ; 20/11/2015 1796 ; 24/10/2015 1797 00000786 2EFF15[54300000] call dword [cs:com1_irq4] 1798 0000078D 6A04 push dword 4 1799 0000078F EB2A jmp short which_irq 1800 irq5: 1801 00000791 6A05 push dword 5 1802 00000793 EB26 jmp short which_irq 1803 irq6: 1804 00000795 6A06 push dword 6 1805 00000797 EB22 jmp short which_irq 1806 irq7: 1807 00000799 6A07 push dword 7 1808 0000079B EB1E jmp short which_irq 1809 irq8: 1810 0000079D 6A08 push dword 8 1811 0000079F EB1A jmp short which_irq 1812 irq9: 1813 000007A1 6A09 push dword 9 1814 000007A3 EB16 jmp short which_irq 1815 irq10: 1816 000007A5 6A0A push dword 10 1817 000007A7 EB12 jmp short which_irq 1818 irq11: 1819 000007A9 6A0B push dword 11 1820 000007AB EB0E jmp short which_irq 1821 irq12: 1822 000007AD 6A0C push dword 12 1823 000007AF EB0A jmp short which_irq 1824 irq13: 1825 000007B1 6A0D push dword 13 1826 000007B3 EB06 jmp short which_irq 1827 irq14: 1828 000007B5 6A0E push dword 14 1829 000007B7 EB02 jmp short which_irq 1830 irq15: 1831 000007B9 6A0F push dword 15 1832 ;jmp short which_irq 1833 1834 ; 19/10/2015 1835 ; 29/08/2014 1836 ; 21/08/2014 1837 which_irq: 1838 000007BB 870424 xchg eax, [esp] ; 28/08/2014 1839 000007BE 53 push ebx 1840 000007BF 56 push esi 1841 000007C0 57 push edi 1842 000007C1 1E push ds 1843 000007C2 06 push es 1844 ; 1845 000007C3 88C3 mov bl, al 1846 ; 1847 000007C5 B810000000 mov eax, KDATA 1848 000007CA 8ED8 mov ds, ax 1849 000007CC 8EC0 mov es, ax 1850 ; 19/10/2015 1851 000007CE FC cld 1852 ; 27/08/2014 1853 000007CF 8105[BC620000]A000- add dword [scr_row], 0A0h 1854 000007D7 0000 1855 ; 1856 000007D9 B417 mov ah, 17h ; blue (1) background, 1857 ; light gray (7) forecolor 1858 000007DB 8B3D[BC620000] mov edi, [scr_row] 1859 000007E1 B049 mov al, 'I' 1860 000007E3 66AB stosw 1861 000007E5 B052 mov al, 'R' 1862 000007E7 66AB stosw 1863 000007E9 B051 mov al, 'Q' 1864 000007EB 66AB stosw 1865 000007ED B020 mov al, ' ' 1866 000007EF 66AB stosw 1867 000007F1 88D8 mov al, bl 1868 000007F3 3C0A cmp al, 10 1869 000007F5 7208 jb short iix 1870 000007F7 B031 mov al, '1' 1871 000007F9 66AB stosw 1872 000007FB 88D8 mov al, bl 1873 000007FD 2C0A sub al, 10 1874 iix: 1875 000007FF 0430 add al, '0' 1876 00000801 66AB stosw 1877 00000803 B020 mov al, ' ' 1878 00000805 66AB stosw 1879 00000807 B021 mov al, '!' 1880 00000809 66AB stosw 1881 0000080B B020 mov al, ' ' 1882 0000080D 66AB stosw 1883 ; 23/02/2015 1884 0000080F 80FB07 cmp bl, 7 ; check for IRQ 8 to IRQ 15 1885 ;jna iiret 1886 ; 04/12/2021 1887 00000812 7604 jna short iiz 1888 iiy: 1889 00000814 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1890 00000816 E6A0 out 0A0h, al ; the 2nd 8259 1891 iiz: 1892 00000818 E983010000 jmp iiret 1893 ; 1894 ; 22/08/2014 1895 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1896 ;out 20h, al ; 8259 PORT 1897 ; 1898 ;pop es 1899 ;pop ds 1900 ;pop edi 1901 ;pop esi 1902 ;pop ebx 1903 ;pop eax 1904 ;iret 1905 1906 ; 02/04/2015 1907 ; 25/08/2014 1908 exc0: 1909 0000081D 6A00 push dword 0 1910 0000081F E990000000 jmp cpu_except 1911 exc1: 1912 00000824 6A01 push dword 1 1913 00000826 E989000000 jmp cpu_except 1914 exc2: 1915 0000082B 6A02 push dword 2 1916 0000082D E982000000 jmp cpu_except 1917 exc3: 1918 00000832 6A03 push dword 3 1919 00000834 EB7E jmp cpu_except 1920 exc4: 1921 00000836 6A04 push dword 4 1922 00000838 EB7A jmp cpu_except 1923 exc5: 1924 0000083A 6A05 push dword 5 1925 0000083C EB76 jmp cpu_except 1926 exc6: 1927 0000083E 6A06 push dword 6 1928 00000840 EB72 jmp cpu_except 1929 exc7: 1930 00000842 6A07 push dword 7 1931 00000844 EB6E jmp cpu_except 1932 exc8: 1933 ; [esp] = Error code 1934 00000846 6A08 push dword 8 1935 00000848 EB5C jmp cpu_except_en 1936 exc9: 1937 0000084A 6A09 push dword 9 1938 0000084C EB66 jmp cpu_except 1939 exc10: 1940 ; [esp] = Error code 1941 0000084E 6A0A push dword 10 1942 00000850 EB54 jmp cpu_except_en 1943 exc11: 1944 ; [esp] = Error code 1945 00000852 6A0B push dword 11 1946 00000854 EB50 jmp cpu_except_en 1947 exc12: 1948 ; [esp] = Error code 1949 00000856 6A0C push dword 12 1950 00000858 EB4C jmp cpu_except_en 1951 exc13: 1952 ; [esp] = Error code 1953 0000085A 6A0D push dword 13 1954 0000085C EB48 jmp cpu_except_en 1955 exc14: 1956 ; [esp] = Error code 1957 0000085E 6A0E push dword 14 1958 00000860 EB44 jmp short cpu_except_en 1959 exc15: 1960 00000862 6A0F push dword 15 1961 00000864 EB4E jmp cpu_except 1962 exc16: 1963 00000866 6A10 push dword 16 1964 00000868 EB4A jmp cpu_except 1965 exc17: 1966 ; [esp] = Error code 1967 0000086A 6A11 push dword 17 1968 0000086C EB38 jmp short cpu_except_en 1969 exc18: 1970 0000086E 6A12 push dword 18 1971 00000870 EB42 jmp short cpu_except 1972 exc19: 1973 00000872 6A13 push dword 19 1974 00000874 EB3E jmp short cpu_except 1975 exc20: 1976 00000876 6A14 push dword 20 1977 00000878 EB3A jmp short cpu_except 1978 exc21: 1979 0000087A 6A15 push dword 21 1980 0000087C EB36 jmp short cpu_except 1981 exc22: 1982 0000087E 6A16 push dword 22 1983 00000880 EB32 jmp short cpu_except 1984 exc23: 1985 00000882 6A17 push dword 23 1986 00000884 EB2E jmp short cpu_except 1987 exc24: 1988 00000886 6A18 push dword 24 1989 00000888 EB2A jmp short cpu_except 1990 exc25: 1991 0000088A 6A19 push dword 25 1992 0000088C EB26 jmp short cpu_except 1993 exc26: 1994 0000088E 6A1A push dword 26 1995 00000890 EB22 jmp short cpu_except 1996 exc27: 1997 00000892 6A1B push dword 27 1998 00000894 EB1E jmp short cpu_except 1999 exc28: 2000 00000896 6A1C push dword 28 2001 00000898 EB1A jmp short cpu_except 2002 exc29: 2003 0000089A 6A1D push dword 29 2004 0000089C EB16 jmp short cpu_except 2005 exc30: 2006 0000089E 6A1E push dword 30 2007 000008A0 EB04 jmp short cpu_except_en 2008 exc31: 2009 000008A2 6A1F push dword 31 2010 000008A4 EB0E jmp short cpu_except 2011 2012 ; 02/01/2022 (Retro UNIX 386 v1.2) 2013 ; 19/10/2015 2014 ; 19/09/2015 2015 ; 01/09/2015 2016 ; 28/08/2015 2017 ; 28/08/2014 2018 cpu_except_en: 2019 000008A6 87442404 xchg eax, [esp+4] ; Error code 2020 000008AA 36A3[14680000] mov [ss:error_code], eax 2021 000008B0 58 pop eax ; Exception number 2022 000008B1 870424 xchg eax, [esp] 2023 ; eax = eax before exception 2024 ; [esp] -> exception number 2025 ; [esp+4] -> EIP to return 2026 ; 19/10/2015 2027 ; 19/09/2015 2028 ; 01/09/2015 2029 ; 28/08/2015 2030 ; 29/08/2014 2031 ; 28/08/2014 2032 ; 25/08/2014 2033 ; 21/08/2014 2034 cpu_except: ; CPU Exceptions 2035 000008B4 FC cld 2036 000008B5 870424 xchg eax, [esp] 2037 ; eax = Exception number 2038 ; [esp] = eax (before exception) 2039 000008B8 53 push ebx 2040 000008B9 56 push esi 2041 000008BA 57 push edi 2042 000008BB 1E push ds 2043 000008BC 06 push es 2044 ; 28/08/2015 2045 000008BD 66BB1000 mov bx, KDATA 2046 000008C1 8EDB mov ds, bx 2047 000008C3 8EC3 mov es, bx 2048 000008C5 0F20DB mov ebx, cr3 2049 000008C8 53 push ebx ; (*) page directory 2050 ; 19/10/2015 2051 000008C9 FC cld 2052 ; 25/03/2015 2053 000008CA 8B1D[68670000] mov ebx, [k_page_dir] 2054 000008D0 0F22DB mov cr3, ebx 2055 ; 28/08/2015 2056 000008D3 83F80E cmp eax, 0Eh ; 14, PAGE FAULT 2057 000008D6 7513 jne short cpu_except_nfp 2058 000008D8 E8B31D0000 call page_fault_handler 2059 000008DD 21C0 and eax, eax 2060 ;jz iiretp ; 01/09/2015 2061 ; 02/01/2022 2062 000008DF 7505 jnz short cpu_except_pf 2063 000008E1 E9B6000000 jmp iiretp 2064 cpu_except_pf: 2065 000008E6 B80E000000 mov eax, 0Eh ; 14 2066 cpu_except_nfp: 2067 ; 02/04/2015 2068 000008EB BB[15060000] mov ebx, hang 2069 000008F0 875C241C xchg ebx, [esp+28] 2070 ; EIP (points to instruction which faults) 2071 ; New EIP (hang) 2072 000008F4 891D[18680000] mov [FaultOffset], ebx 2073 000008FA C744242008000000 mov dword [esp+32], KCODE ; kernel's code segment 2074 00000902 814C242400020000 or dword [esp+36], 200h ; enable interrupts (set IF) 2075 ; 2076 0000090A 88C4 mov ah, al 2077 0000090C 240F and al, 0Fh 2078 0000090E 3C09 cmp al, 9 2079 00000910 7602 jna short h1ok 2080 00000912 0407 add al, 'A'-':' 2081 h1ok: 2082 00000914 D0EC shr ah, 1 2083 00000916 D0EC shr ah, 1 2084 00000918 D0EC shr ah, 1 2085 0000091A D0EC shr ah, 1 2086 0000091C 80FC09 cmp ah, 9 2087 0000091F 7603 jna short h2ok 2088 00000921 80C407 add ah, 'A'-':' 2089 h2ok: 2090 00000924 86E0 xchg ah, al 2091 00000926 66053030 add ax, '00' 2092 0000092A 66A3[4A630000] mov [excnstr], ax 2093 ; 2094 ; 29/08/2014 2095 00000930 A1[18680000] mov eax, [FaultOffset] 2096 00000935 51 push ecx 2097 00000936 52 push edx 2098 00000937 89E3 mov ebx, esp 2099 ; 28/08/2015 2100 00000939 B910000000 mov ecx, 16 ; divisor value to convert binary number 2101 ; to hexadecimal string 2102 ;mov ecx, 10 ; divisor to convert 2103 ; binary number to decimal string 2104 b2d1: 2105 0000093E 31D2 xor edx, edx 2106 00000940 F7F1 div ecx 2107 ;push dx 2108 ; 02/01/2022 2109 00000942 52 push edx 2110 00000943 39C8 cmp eax, ecx 2111 00000945 73F7 jnb short b2d1 2112 00000947 BF[55630000] mov edi, EIPstr ; EIP value 2113 ; points to instruction which faults 2114 ; 28/08/2015 2115 0000094C 89C2 mov edx, eax 2116 b2d2: 2117 ;add al, '0' 2118 0000094E 8A82[F0150000] mov al, [edx+hexchrs] 2119 00000954 AA stosb ; write hexadecimal digit to its place 2120 00000955 39E3 cmp ebx, esp 2121 00000957 7605 jna short b2d3 2122 ; 02/01/2022 2123 00000959 58 pop eax 2124 ;pop ax 2125 0000095A 88C2 mov dl, al 2126 0000095C EBF0 jmp short b2d2 2127 b2d3: 2128 0000095E B068 mov al, 'h' ; 28/08/2015 2129 00000960 AA stosb 2130 00000961 B020 mov al, 20h ; space 2131 00000963 AA stosb 2132 00000964 30C0 xor al, al ; to do it an ASCIIZ string 2133 00000966 AA stosb 2134 ; 2135 00000967 5A pop edx 2136 00000968 59 pop ecx 2137 ; 2138 00000969 B44F mov ah, 4Fh ; red (4) background, 2139 ; white (F) forecolor 2140 0000096B BE[3A630000] mov esi, exc_msg ; message offset 2141 ; 2142 00000970 EB11 jmp short piemsg 2143 ; 2144 ;add dword [scr_row], 0A0h 2145 ;mov edi, [scr_row] 2146 ; 2147 ;call printk 2148 ; 2149 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 2150 ;out 20h, al ; 8259 PORT 2151 ; 2152 ;pop es 2153 ;pop ds 2154 ;pop edi 2155 ;pop esi 2156 ;pop eax 2157 ;iret 2158 2159 ; 28/08/2015 2160 ; 23/02/2015 2161 ; 20/08/2014 2162 ignore_int: 2163 00000972 50 push eax 2164 00000973 53 push ebx ; 23/02/2015 2165 00000974 56 push esi 2166 00000975 57 push edi 2167 00000976 1E push ds 2168 00000977 06 push es 2169 ; 28/08/2015 2170 00000978 0F20D8 mov eax, cr3 2171 0000097B 50 push eax ; (*) page directory 2172 ; 2173 0000097C B467 mov ah, 67h ; brown (6) background, 2174 ; light gray (7) forecolor 2175 0000097E BE[F8620000] mov esi, int_msg ; message offset 2176 piemsg: 2177 ; 27/08/2014 2178 00000983 8105[BC620000]A000- add dword [scr_row], 0A0h 2179 0000098B 0000 2180 0000098D 8B3D[BC620000] mov edi, [scr_row] 2181 ; 2182 00000993 E8B6FCFFFF call printk 2183 ; 2184 ; 23/02/2015 2185 00000998 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 2186 0000099A E6A0 out 0A0h, al ; the 2nd 8259 2187 iiretp: ; 01/09/2015 2188 ; 28/08/2015 2189 0000099C 58 pop eax ; (*) page directory 2190 0000099D 0F22D8 mov cr3, eax 2191 ; 2192 iiret: 2193 ; 22/08/2014 2194 000009A0 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 2195 000009A2 E620 out 20h, al ; 8259 PORT 2196 ; 2197 000009A4 07 pop es 2198 000009A5 1F pop ds 2199 000009A6 5F pop edi 2200 000009A7 5E pop esi 2201 000009A8 5B pop ebx ; 29/08/2014 2202 000009A9 58 pop eax 2203 000009AA CF iretd 2204 2205 ; 23/02/2022 2206 ; 26/02/2015 2207 ; 07/09/2014 2208 ; 25/08/2014 2209 rtc_int: ; Real Time Clock Interrupt (IRQ 8) 2210 ; 22/08/2014 2211 000009AB 50 push eax 2212 000009AC 53 push ebx ; 29/08/2014 2213 000009AD 56 push esi 2214 000009AE 57 push edi 2215 000009AF 1E push ds 2216 000009B0 06 push es 2217 ; 2218 000009B1 B810000000 mov eax, KDATA 2219 000009B6 8ED8 mov ds, ax 2220 000009B8 8EC0 mov es, ax 2221 ; 2222 ; 25/08/2014 2223 ;call rtc_p 2224 ; 23/02/2022 2225 000009BA FF15[0D070000] call [x_rtci] 2226 ; 2227 ; 22/02/2015 - dsectpm.s 2228 ; [ source: http://wiki.osdev.org/RTC ] 2229 ; read status register C to complete procedure 2230 ;(it is needed to get a next IRQ 8) 2231 000009C0 B00C mov al, 0Ch ; 2232 000009C2 E670 out 70h, al ; select register C 2233 000009C4 90 nop 2234 000009C5 E471 in al, 71h ; just throw away contents 2235 ; 22/02/2015 2236 000009C7 B020 MOV AL,EOI ; END OF INTERRUPT 2237 000009C9 E6A0 OUT INTB00,AL ; FOR CONTROLLER #2 2238 ; 2239 000009CB EBD3 jmp short iiret 2240 2241 ; 22/08/2014 2242 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm) 2243 ; (INT 1Ah) 2244 ;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991) 2245 time_of_day: 2246 000009CD E866010000 call UPD_IPR ; WAIT TILL UPDATE NOT IN PROGRESS 2247 000009D2 726F jc short rtc_retn 2248 000009D4 B000 mov al, CMOS_SECONDS 2249 000009D6 E847010000 call CMOS_READ 2250 000009DB A2[DC670000] mov [time_seconds], al 2251 000009E0 B002 mov al, CMOS_MINUTES 2252 000009E2 E83B010000 call CMOS_READ 2253 000009E7 A2[DD670000] mov [time_minutes], al 2254 000009EC B004 mov al, CMOS_HOURS 2255 000009EE E82F010000 call CMOS_READ 2256 000009F3 A2[DE670000] mov [time_hours], al 2257 000009F8 B006 mov al, CMOS_DAY_WEEK 2258 000009FA E823010000 call CMOS_READ 2259 000009FF A2[DF670000] mov [date_wday], al 2260 00000A04 B007 mov al, CMOS_DAY_MONTH 2261 00000A06 E817010000 call CMOS_READ 2262 00000A0B A2[E0670000] mov [date_day], al 2263 00000A10 B008 mov al, CMOS_MONTH 2264 00000A12 E80B010000 call CMOS_READ 2265 00000A17 A2[E1670000] mov [date_month], al 2266 00000A1C B009 mov al, CMOS_YEAR 2267 00000A1E E8FF000000 call CMOS_READ 2268 00000A23 A2[E2670000] mov [date_year], al 2269 00000A28 B032 mov al, CMOS_CENTURY 2270 00000A2A E8F3000000 call CMOS_READ 2271 00000A2F A2[E3670000] mov [date_century], al 2272 ; 2273 00000A34 B000 mov al, CMOS_SECONDS 2274 00000A36 E8E7000000 call CMOS_READ 2275 00000A3B 3A05[DC670000] cmp al, [time_seconds] 2276 00000A41 758A jne short time_of_day 2277 2278 rtc_retn: 2279 00000A43 C3 retn 2280 2281 rtci_default: 2282 ; 23/02/2022 (Temporary!) 2283 ; (default real time clock handler in multitasking mode) 2284 ; ((2 rtc ticks per second after 'setup_rtc_int')) 2285 00000A44 FF05[20680000] inc dword [rtc_ticks] ; real time clock counter 2286 ; (not used in anywhere of kernel for now!) 2287 00000A4A C3 retn 2288 2289 rtc_p: 2290 ; 27/12/2021 (Retro UNIX 386 v1.2) 2291 ; 07/09/2014 2292 ; 29/08/2014 2293 ; 27/08/2014 2294 ; 25/08/2014 2295 ; Print Real Time Clock content 2296 ; 2297 ; 2298 00000A4B E87DFFFFFF call time_of_day 2299 00000A50 72F1 jc short rtc_retn 2300 ; 2301 00000A52 3A05[AC630000] cmp al, [ptime_seconds] 2302 00000A58 74E9 je short rtc_retn ; 29/08/2014 2303 ; 2304 00000A5A A2[AC630000] mov [ptime_seconds], al 2305 ; 2306 00000A5F A0[E3670000] mov al, [date_century] 2307 00000A64 E8EA000000 call bcd_to_ascii 2308 00000A69 66A3[79630000] mov [datestr+6], ax 2309 00000A6F A0[E2670000] mov al, [date_year] 2310 00000A74 E8DA000000 call bcd_to_ascii 2311 00000A79 66A3[7B630000] mov [datestr+8], ax 2312 00000A7F A0[E1670000] mov al, [date_month] 2313 00000A84 E8CA000000 call bcd_to_ascii 2314 00000A89 66A3[76630000] mov [datestr+3], ax 2315 00000A8F A0[E0670000] mov al, [date_day] 2316 00000A94 E8BA000000 call bcd_to_ascii 2317 00000A99 66A3[73630000] mov [datestr], ax 2318 ; 2319 00000A9F 0FB61D[DF670000] movzx ebx, byte [date_wday] 2320 00000AA6 C0E302 shl bl, 2 2321 00000AA9 81C3[8C630000] add ebx, daytmp 2322 00000AAF 8B03 mov eax, [ebx] 2323 00000AB1 A3[7E630000] mov [daystr], eax 2324 ; 2325 00000AB6 A0[DE670000] mov al, [time_hours] 2326 00000ABB E893000000 call bcd_to_ascii 2327 00000AC0 66A3[82630000] mov [timestr], ax 2328 00000AC6 A0[DD670000] mov al, [time_minutes] 2329 00000ACB E883000000 call bcd_to_ascii 2330 00000AD0 66A3[85630000] mov [timestr+3], ax 2331 00000AD6 A0[DC670000] mov al, [time_seconds] 2332 00000ADB E873000000 call bcd_to_ascii 2333 00000AE0 66A3[88630000] mov [timestr+6], ax 2334 ; 2335 00000AE6 BE[61630000] mov esi, rtc_msg ; message offset 2336 ; 23/02/2015 2337 00000AEB 52 push edx 2338 00000AEC 51 push ecx 2339 ; 07/09/2014 2340 ;mov bx, 2 ; Video page 2 2341 ; 27/12/2021 2342 00000AED 29DB sub ebx, ebx 2343 ;mov bl, 2 2344 ; 15/02/2022 2345 00000AEF B307 mov bl, 7 ; Video page 7 2346 prtmsg: 2347 00000AF1 AC lodsb 2348 00000AF2 08C0 or al, al 2349 00000AF4 740D jz short prtmsg_ok 2350 00000AF6 56 push esi 2351 ;push bx 2352 00000AF7 53 push ebx ; 27/12/2021 2353 00000AF8 B43F mov ah, 3Fh ; cyan (6) background, 2354 ; white (F) forecolor 2355 00000AFA E8B5070000 call write_tty 2356 ;pop bx 2357 00000AFF 5B pop ebx ; 27/12/2021 2358 00000B00 5E pop esi 2359 00000B01 EBEE jmp short prtmsg 2360 ; 2361 ;mov edi, 0B8000h+0A0h+0A0h ; Row 2 2362 ;call printk 2363 prtmsg_ok: 2364 ; 07/09/2014 2365 ;xor dx, dx ; column 0, row 0 2366 ; 27/12/2021 2367 00000B03 31D2 xor edx, edx 2368 00000B05 E8B4080000 call set_cpos ; set curspor position to 0,0 2369 ; 23/02/2015 2370 00000B0A 59 pop ecx 2371 00000B0B 5A pop edx 2372 00000B0C C3 retn 2373 2374 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 2375 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 2376 default_irq7: 2377 ; 04/12/2021 2378 ;push ax 2379 00000B0D 50 push eax 2380 00000B0E B00B mov al, 0Bh ; In-Service register 2381 00000B10 E620 out 20h, al 2382 00000B12 EB00 jmp short $+2 2383 00000B14 EB00 jmp short $+2 2384 00000B16 E420 in al, 20h 2385 00000B18 2480 and al, 80h ; bit 7 (is it real IRQ 7 or fake?) 2386 00000B1A 7404 jz short irq7_iret ; Fake (spurious) IRQ, do not send EOI 2387 00000B1C B020 mov al, 20h ; EOI 2388 00000B1E E620 out 20h, al 2389 irq7_iret: 2390 ;pop ax 2391 ; 04/12/2021 2392 00000B20 58 pop eax 2393 00000B21 CF iretd 2394 2395 ; 04/12/2021 2396 ; 22/08/2014 2397 ; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm) 2398 CMOS_READ: 2399 00000B22 9C pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 2400 00000B23 D0C0 rol al, 1 ; MOVE NMI BIT TO LOW POSITION 2401 00000B25 F9 stc ; FORCE NMI BIT ON IN CARRY FLAG 2402 00000B26 D0D8 rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 2403 00000B28 FA cli ; DISABLE INTERRUPTS 2404 00000B29 E670 out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 2405 00000B2B 90 nop ; I/O DELAY 2406 00000B2C E471 in al, CMOS_DATA ; READ THE REQUESTED CMOS LOCATION 2407 ;push ax ; SAVE (AH) REGISTER VALUE AND CMOS BYTE 2408 ; 04/12/2021 2409 00000B2E 50 push eax 2410 ; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 2411 ; ----- 10/06/85 (test4.asm) 2412 00000B2F B01E mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 2413 ;mov al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION 2414 00000B31 D0D8 rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 2415 00000B33 E670 out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 2416 ;pop ax ; RESTORE (AH) AND (AL), CMOS BYTE 2417 ; 04/12/2021 2418 00000B35 58 pop eax 2419 00000B36 9D popf 2420 00000B37 C3 retn ; RETURN WITH FLAGS RESTORED 2421 2422 ; 22/08/2014 2423 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm) 2424 UPD_IPR: ; WAIT TILL UPDATE NOT IN PROGRESS 2425 00000B38 51 push ecx 2426 00000B39 B9FFFF0000 mov ecx, 65535 ; SET TIMEOUT LOOP COUNT (= 800) 2427 ; mov cx, 800 2428 UPD_10: 2429 00000B3E B00A mov al, CMOS_REG_A ; ADDRESS STATUS REGISTER A 2430 00000B40 FA cli ; NO TIMER INTERRUPTS DURING UPDATES 2431 00000B41 E8DCFFFFFF call CMOS_READ ; READ UPDATE IN PROCESS FLAG 2432 00000B46 A880 test al, 80h ; IF UIP BIT IS ON ( CANNOT READ TIME ) 2433 00000B48 7406 jz short UPD_90 ; EXIT WITH CY= 0 IF CAN READ CLOCK NOW 2434 00000B4A FB sti ; ALLOW INTERRUPTS WHILE WAITING 2435 00000B4B E2F1 loop UPD_10 ; LOOP TILL READY OR TIMEOUT 2436 00000B4D 31C0 xor eax, eax ; CLEAR RESULTS IF ERROR 2437 ; xor ax, ax 2438 00000B4F F9 stc ; SET CARRY FOR ERROR 2439 UPD_90: 2440 00000B50 59 pop ecx ; RESTORE CALLERS REGISTER 2441 00000B51 FA cli ; INTERRUPTS OFF DURING SET 2442 00000B52 C3 retn ; RETURN WITH CY FLAG SET 2443 2444 bcd_to_ascii: 2445 ; 25/08/2014 2446 ; INPUT -> 2447 ; al = Packed BCD number 2448 ; OUTPUT -> 2449 ; ax = ASCII word/number 2450 ; 2451 ; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011) 2452 ; 2453 00000B53 D410 db 0D4h, 10h ; Undocumented inst. AAM 2454 ; AH = AL / 10h 2455 ; AL = AL MOD 10h 2456 00000B55 660D3030 or ax, '00' ; Make it ASCII based 2457 2458 00000B59 86E0 xchg ah, al 2459 2460 00000B5B C3 retn 2461 2462 2463 %include 'keyboard.s' ; 07/03/2015 2464 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2465 <1> ; (re-write kernel for test by using previous version without a major defect) 2466 <1> ; **************************************************************************** 2467 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.3) - KEYBOARD.INC 2468 <1> ; Last Modification: 24/07/2022 2469 <1> ; (Keyboard Data is in 'KYBDATA.INC') 2470 <1> ; 2471 <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) /////////////// 2472 <1> 2473 <1> ; 24/07/2022 2474 <1> ; (Retro UNIX 386 v1.2, Kernel v0.2.2.3) 2475 <1> ; (Retro UNIX 386 v1.1, Kernel v0.2.1.6) 2476 <1> ; (Retro UNIX 386 v1.0, Kernel v0.2.0.22) 2477 <1> ; 23/02/2022 2478 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2479 <1> ; 30/06/2015 2480 <1> ; 11/03/2015 2481 <1> ; 28/02/2015 2482 <1> ; 25/02/2015 2483 <1> ; 20/02/2015 2484 <1> ; 18/02/2015 2485 <1> ; 03/12/2014 2486 <1> ; 07/09/2014 2487 <1> ; KEYBOARD INTERRUPT HANDLER 2488 <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014) 2489 <1> 2490 <1> ;getch: 2491 <1> ; ; 18/02/2015 2492 <1> ; ; This routine will be replaced with Retro UNIX 386 2493 <1> ; ; version of Retro UNIX 8086 getch (tty input) 2494 <1> ; ; routine, later... (multi tasking ability) 2495 <1> ; ; 28/02/2015 2496 <1> ; sti ; enable interrupts 2497 <1> ; ; 2498 <1> ; ;push esi 2499 <1> ; ;push ebx 2500 <1> ; ;xor ebx, ebx 2501 <1> ; ;mov bl, [ptty] ; active_page 2502 <1> ; ;mov esi, ebx 2503 <1> ; ;shl si, 1 2504 <1> ; ;add esi, ttychr 2505 <1> ;getch_1: 2506 <1> ; ;mov ax, [esi] 2507 <1> ; mov ax, [ttychr] ; video page 0 (tty0) 2508 <1> ; and ax, ax 2509 <1> ; jz short getch_2 2510 <1> ; mov word [ttychr], 0 2511 <1> ; ;mov word [esi], 0 2512 <1> ; ;pop ebx 2513 <1> ; ;pop esi 2514 <1> ; retn 2515 <1> ;getch_2: 2516 <1> ; hlt ; not proper for multi tasking! 2517 <1> ; ; (temporary halt for now) 2518 <1> ; ; 'sleep' on tty 2519 <1> ; ; will (must) be located here 2520 <1> ; nop 2521 <1> ; jmp short getch_1 2522 <1> 2523 <1> keyb_int: 2524 <1> ; 24/07/2022 2525 <1> ; 23/02/2022 2526 <1> ; 30/06/2015 2527 <1> ; 25/02/2015 2528 <1> ; 20/02/2015 2529 <1> ; 03/12/2014 (getc_int - INT 16h modifications) 2530 <1> ; 07/09/2014 - Retro UNIX 386 v1 2531 <1> ; 30/06/2014 2532 <1> ; 10/05/2013 2533 <1> ; Retro Unix 8086 v1 feature only! 2534 <1> ; 03/03/2014 2535 <1> 2536 00000B5C 1E <1> push ds 2537 00000B5D 53 <1> push ebx 2538 00000B5E 50 <1> push eax 2539 <1> ; 2540 <1> ; 23/02/2022 2541 00000B5F 9C <1> pushfd 2542 00000B60 0E <1> push cs 2543 <1> ;mov ax, KDATA 2544 00000B61 31C0 <1> xor eax, eax 2545 00000B63 B010 <1> mov al, KDATA 2546 00000B65 8ED8 <1> mov ds, ax 2547 <1> ; 2548 <1> ;pushfd 2549 <1> ;push cs 2550 00000B67 E80A010000 <1> call kb_int ; int_09h 2551 <1> ; 2552 <1> ;mov ah, 11h ; 03/12/2014 2553 00000B6C B401 <1> mov ah, 1 ; 24/07/2022 2554 <1> ;call getc 2555 00000B6E E854000000 <1> call int_16h ; 30/06/2015 2556 00000B73 744E <1> jz short keyb_int4 2557 <1> ; 2558 <1> ;mov ah, 10h ; 03/12/2014 2559 00000B75 B400 <1> mov ah, 0 ; 24/07/2022 2560 <1> ;call getc 2561 00000B77 E84B000000 <1> call int_16h ; 30/06/2015 2562 <1> ; 2563 <1> ; 20/02/2015 2564 00000B7C 0FB61D[96670000] <1> movzx ebx, byte [ptty] ; active_page 2565 <1> ; 2566 00000B83 20C0 <1> and al, al 2567 00000B85 751D <1> jnz short keyb_int1 2568 <1> ; 2569 00000B87 80FC68 <1> cmp ah, 68h ; ALT + F1 key 2570 00000B8A 7218 <1> jb short keyb_int1 2571 00000B8C 80FC6F <1> cmp ah, 6Fh ; ALT + F8 key 2572 00000B8F 7713 <1> ja short keyb_int1 2573 <1> ; 2574 00000B91 88D8 <1> mov al, bl 2575 00000B93 0468 <1> add al, 68h 2576 00000B95 38E0 <1> cmp al, ah 2577 00000B97 7409 <1> je short keyb_int0 2578 00000B99 88E0 <1> mov al, ah 2579 00000B9B 2C68 <1> sub al, 68h 2580 00000B9D E831090000 <1> call tty_sw 2581 <1> ;movzx ebx, [ptty] ; active_page 2582 <1> keyb_int0: ; 30/06/2015 2583 <1> ;xor ax, ax 2584 <1> ; 23/02/2022 2585 00000BA2 31C0 <1> xor eax, eax 2586 <1> keyb_int1: 2587 00000BA4 D0E3 <1> shl bl, 1 2588 00000BA6 81C3[98670000] <1> add ebx, ttychr 2589 <1> ; 2590 <1> ;23/02/2022 2591 00000BAC 09C0 <1> or eax, eax 2592 <1> ;or ax, ax 2593 00000BAE 7406 <1> jz short keyb_int2 2594 <1> ; 2595 00000BB0 66833B00 <1> cmp word [ebx], 0 2596 00000BB4 7703 <1> ja short keyb_int3 2597 <1> keyb_int2: 2598 00000BB6 668903 <1> mov [ebx], ax ; Save ascii code 2599 <1> ; and scan code of the character 2600 <1> ; for current tty (or last tty 2601 <1> ; just before tty switch). 2602 <1> keyb_int3: 2603 00000BB9 A0[96670000] <1> mov al, [ptty] 2604 00000BBE E88F3B0000 <1> call wakeup 2605 <1> ; 2606 <1> keyb_int4: 2607 00000BC3 58 <1> pop eax 2608 00000BC4 5B <1> pop ebx 2609 00000BC5 1F <1> pop ds 2610 00000BC6 CF <1> iret 2611 <1> 2612 <1> ; 18/02/2015 2613 <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc. 2614 <1> ; 'keyb_int' always handles 'getc' at 1st and puts the 2615 <1> ; scancode and ascii code of the character 2616 <1> ; in the tty input (ttychr) buffer. 2617 <1> ; Test procedures must call 'getch' for tty input 2618 <1> ; otherwise, 'getc' will not be able to return to the caller 2619 <1> ; due to infinite (key press) waiting loop. 2620 <1> ; 2621 <1> ; 03/12/2014 2622 <1> ; 26/08/2014 2623 <1> ; KEYBOARD I/O 2624 <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014) 2625 <1> 2626 <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers. 2627 <1> ; (The reason of using '_k' labels!!!) (27/08/2014) 2628 <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM. 2629 <1> ; ('NOT LC_HC' --> '~LC_HC') (bit reversing operator) 2630 <1> 2631 <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2632 <1> ;int_16h: ; 30/06/2015 2633 <1> ;;getc: 2634 <1> ; pushfd ; 28/08/2014 2635 <1> ; push cs 2636 <1> ; call getc_int 2637 <1> ; retn 2638 <1> 2639 <1> ; 24/07/2022 2640 <1> %if 0 2641 <1> ; 24/12/2021 2642 <1> 2643 <1> ;----- SHIFT STATUS 2644 <1> _K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2645 <1> mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2646 <1> and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2647 <1> ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2648 <1> ;shl ah, cl ; BIT 7 POSITION 2649 <1> shl ah, 5 2650 <1> mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2651 <1> and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2652 <1> or ah, al ; MERGE REMAINING BITS INTO AH 2653 <1> mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2654 <1> and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2655 <1> or ah, al ; OR THE SHIFT FLAGS TOGETHER 2656 <1> _K3: 2657 <1> mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2658 <1> jmp short _KIO_EXIT ; RETURN TO CALLER 2659 <1> 2660 <1> %endif 2661 <1> 2662 <1> int_16h: 2663 <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2664 <1> ; 24/07/2022 - (near call return instead of interrupt return) 2665 <1> 2666 <1> ; INPUT: 2667 <1> ; AL = Function (0 or 1) 2668 <1> ; 0 = Read Character 2669 <1> ; 1 = Get Keyboard Buffer Status 2670 <1> ; OUTPUT: 2671 <1> ; Function 0 - AX = ASCII (AL) and SCAN CODE (AH) 2672 <1> ; of the character (enterrd from the keyboard) 2673 <1> ; Function 1 - If ZF = 0 2674 <1> ; AX = ASCII (AL) and SCAN CODE (AH) of the character 2675 <1> ; (which is waiting in keyboard buffer) 2676 <1> ; If ZF = 1 2677 <1> ; there is not a character in the keyboard buffer 2678 <1> ; 2679 <1> ; Modified registers: eax, ebx 2680 <1> 2681 <1> getc_int: 2682 <1> ; 24/07/2022 (Retro UNIX 386 v1.1 - Kernel v0.2.1.6) 2683 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2684 <1> ; 28/02/2015 2685 <1> ; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2686 <1> ; instead of pc-at bios - 1985-) 2687 <1> ; 28/08/2014 (_k1d) 2688 <1> ; 30/06/2014 2689 <1> ; 03/03/2014 2690 <1> ; 28/02/2014 2691 <1> ; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 2692 <1> ; rombios source code (21/04/1986) 2693 <1> ; 'keybd.asm', INT 16H, KEYBOARD_IO 2694 <1> ; 2695 <1> ; KYBD --- 03/06/86 KEYBOARD BIOS 2696 <1> ; 2697 <1> ;--- INT 16 H ----------------------------------------------------------------- 2698 <1> ; KEYBOARD I/O : 2699 <1> ; THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT : 2700 <1> ; INPUT : 2701 <1> ; (AH)= 00H READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD, : 2702 <1> ; RETURN THE RESULT IN (AL), SCAN CODE IN (AH). : 2703 <1> ; THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE : 2704 <1> ; STANDARD PC OR PCAT KEYBOARD : 2705 <1> ;-----------------------------------------------------------------------------: 2706 <1> ; (AH)= 01H SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS : 2707 <1> ; AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER. : 2708 <1> ; (ZF)= 1 -- NO CODE AVAILABLE : 2709 <1> ; (ZF)= 0 -- CODE IS AVAILABLE (AX)= CHARACTER : 2710 <1> ; IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS : 2711 <1> ; IN (AX), AND THE ENTRY REMAINS IN THE BUFFER. : 2712 <1> ; THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES : 2713 <1> ;-----------------------------------------------------------------------------: 2714 <1> ; (AH)= 02H RETURN THE CURRENT SHIFT STATUS IN AL REGISTER : 2715 <1> ; THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE : 2716 <1> ; EQUATES FOR @KB_FLAG : 2717 <1> ;-----------------------------------------------------------------------------: 2718 <1> ; (AH)= 03H SET TYPAMATIC RATE AND DELAY : 2719 <1> ; (AL) = 05H : 2720 <1> ; (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0) : 2721 <1> ; : 2722 <1> ; REGISTER RATE REGISTER RATE : 2723 <1> ; VALUE SELECTED VALUE SELECTED : 2724 <1> ; -------------------------------------------- : 2725 <1> ; 00H 30.0 10H 7.5 : 2726 <1> ; 01H 26.7 11H 6.7 : 2727 <1> ; 02H 24.0 12H 6.0 : 2728 <1> ; 03H 21.8 13H 5.5 : 2729 <1> ; 04H 20.0 14H 5.0 : 2730 <1> ; 05H 18.5 15H 4.6 : 2731 <1> ; 06H 17.1 16H 4.3 : 2732 <1> ; 07H 16.0 17H 4.0 : 2733 <1> ; 08H 15.0 18H 3.7 : 2734 <1> ; 09H 13.3 19H 3.3 : 2735 <1> ; 0AH 12.0 1AH 3.0 : 2736 <1> ; 0BH 10.9 1BH 2.7 : 2737 <1> ; 0CH 10.0 1CH 2.5 : 2738 <1> ; 0DH 9.2 1DH 2.3 : 2739 <1> ; 0EH 8.6 1EH 2.1 : 2740 <1> ; 0FH 8.0 1FH 2.0 : 2741 <1> ; : 2742 <1> ; (BH) = TYPAMATIC DELAY (BITS 2 - 7 MUST BE RESET TO 0) : 2743 <1> ; : 2744 <1> ; REGISTER DELAY : 2745 <1> ; VALUE VALUE : 2746 <1> ; ------------------ : 2747 <1> ; 00H 250 ms : 2748 <1> ; 01H 500 ms : 2749 <1> ; 02H 750 ms : 2750 <1> ; 03H 1000 ms : 2751 <1> ;-----------------------------------------------------------------------------: 2752 <1> ; (AH)= 05H PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD : 2753 <1> ; BUFFER AS IF STRUCK FROM KEYBOARD : 2754 <1> ; ENTRY: (CL) = ASCII CHARACTER : 2755 <1> ; (CH) = SCAN CODE : 2756 <1> ; EXIT: (AH) = 00H = SUCCESSFUL OPERATION : 2757 <1> ; (AL) = 01H = UNSUCCESSFUL - BUFFER FULL : 2758 <1> ; FLAGS: CARRY IF ERROR : 2759 <1> ;-----------------------------------------------------------------------------: 2760 <1> ; (AH)= 10H EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD, : 2761 <1> ; OTHERWISE SAME AS FUNCTION AH=0 : 2762 <1> ;-----------------------------------------------------------------------------: 2763 <1> ; (AH)= 11H EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD, : 2764 <1> ; OTHERWISE SAME AS FUNCTION AH=1 : 2765 <1> ;-----------------------------------------------------------------------------: 2766 <1> ; (AH)= 12H RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER : 2767 <1> ; AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT : 2768 <1> ; CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3 : 2769 <1> ; OUTPUT : 2770 <1> ; AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED : 2771 <1> ; ALL REGISTERS RETAINED : 2772 <1> ;------------------------------------------------------------------------------ 2773 <1> 2774 00000BC7 FB <1> sti ; INTERRUPTS BACK ON 2775 <1> 2776 <1> ; 24/07/2022 2777 <1> ;push ds ; SAVE CURRENT DS 2778 <1> ;push ebx ; SAVE BX TEMPORARILY 2779 <1> ;push ecx ; SAVE CX TEMPORARILY 2780 <1> ;mov bx, KDATA 2781 <1> ;mov ds, bx ; PUT SEGMENT VALUE OF DATA AREA INTO DS 2782 <1> 2783 <1> ;or ah, ah ; CHECK FOR (AH)= 00H 2784 <1> ;jz short _K1 ; ASCII_READ 2785 <1> ;dec ah ; CHECK FOR (AH)= 01H 2786 <1> ;jz short _K2 ; ASCII_STATUS 2787 <1> ;dec ah ; CHECK FOR (AH)= 02H 2788 <1> ;jz short _K3 ; SHIFT STATUS 2789 <1> ;dec ah ; CHECK FOR (AH)= 03H 2790 <1> ;jz short _K300 ; SET TYPAMATIC RATE/DELAY 2791 <1> ;sub ah, 2 ; CHECK FOR (AH)= 05H 2792 <1> ;jz short _K500 ; KEYBOARD WRITE 2793 <1> ;_KIO1: 2794 <1> ;sub ah, 11 ; AH = 10H 2795 <1> ;jz short _K1E ; EXTENDED ASCII READ 2796 <1> ;dec ah ; CHECK FOR (AH)= 11H 2797 <1> ;jz short _K2E ; EXTENDED_ASCII_STATUS 2798 <1> ;dec ah ; CHECK FOR (AH)= 12H 2799 <1> ;jz short _K3E ; EXTENDED_SHIFT_STATUS 2800 <1> 2801 <1> ;_KIO_EXIT: 2802 <1> ;pop ecx ; RECOVER REGISTER 2803 <1> ;pop ebx ; RECOVER REGISTER 2804 <1> ; 24/07/2022 2805 <1> ;retn 2806 <1> ;pop ds ; RECOVER SEGMENT 2807 <1> ;iretd ; INVALID COMMAND, EXIT 2808 <1> 2809 00000BC8 08E4 <1> or ah, ah 2810 00000BCA 7507 <1> jnz short _K2 2811 <1> 2812 <1> ;----- ASCII CHARACTER 2813 <1> _K1: 2814 <1> _K1E: 2815 00000BCC E81C000000 <1> call _K1S ; GET A CHARACTER FROM THE BUFFER (EXTENDED) 2816 <1> ;call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2817 <1> ;;jmp short _KIO_EXIT ; GIVE IT TO THE CALLER 2818 <1> ; 24/07/2022 2819 <1> ;retn 2820 00000BD1 EB0F <1> jmp short _KIO_E_XLAT 2821 <1> ;_K1: 2822 <1> ;call _K1S ; GET A CHARACTER FROM THE BUFFER 2823 <1> ;call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2824 <1> ;jc short _K1 ; CARRY SET MEANS TROW CODE AWAY 2825 <1> ;_K1A: 2826 <1> ;jmp short _KIO_EXIT ; RETURN TO CALLER 2827 <1> ; 24/07/2022 2828 <1> ;retn 2829 <1> 2830 <1> ;----- ASCII STATUS 2831 <1> _K2: 2832 <1> _K2E: 2833 00000BD3 E860000000 <1> call _K2S ; TEST FOR CHARACTER IN BUFFER (EXTENDED) 2834 00000BD8 7407 <1> jz short _K2B ; RETURN IF BUFFER EMPTY 2835 00000BDA 9C <1> pushf ; SAVE ZF FROM TEST 2836 00000BDB E802000000 <1> call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2837 <1> ;jmp short _K2A ; GIVE IT TO THE CALLER 2838 <1> ; 24/07/2022 2839 00000BE0 9D <1> popf 2840 <1> _K2B: 2841 00000BE1 C3 <1> retn 2842 <1> ;_K2: 2843 <1> ;call _K2S ; TEST FOR CHARACTER IN BUFFER 2844 <1> ;jz short _K2B ; RETURN IF BUFFER EMPTY 2845 <1> ;pushf ; SAVE ZF FROM TEST 2846 <1> ;call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2847 <1> ;jnc short _K2A ; CARRY CLEAR MEANS PASS VALID CODE 2848 <1> ;popf ; INVALID CODE FOR THIS TYPE OF CALL 2849 <1> ;call _K1S ; THROW THE CHARACTER AWAY 2850 <1> ;jmp short _K2 ; GO LOOK FOR NEXT CHAR, IF ANY 2851 <1> ;_K2A: 2852 <1> ;popf ; RESTORE ZF FROM TEST 2853 <1> ;_K2B: 2854 <1> ;;pop ecx ; RECOVER REGISTER 2855 <1> ;pop ebx ; RECOVER REGISTER 2856 <1> ;pop ds ; RECOVER SEGMENT 2857 <1> ;retf 4 ; THROW AWAY (E)FLAGS 2858 <1> 2859 <1> ; 24/12/2021 2860 <1> ; ;----- SHIFT STATUS 2861 <1> ;_K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2862 <1> ; mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2863 <1> ; and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2864 <1> ; ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2865 <1> ; ;shl ah, cl ; BIT 7 POSITION 2866 <1> ; shl ah, 5 2867 <1> ; mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2868 <1> ; and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2869 <1> ; or ah, al ; MERGE REMAINING BITS INTO AH 2870 <1> ; mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2871 <1> ; and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2872 <1> ; or ah, al ; OR THE SHIFT FLAGS TOGETHER 2873 <1> ;_K3: 2874 <1> ; mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2875 <1> ; jmp short _KIO_EXIT ; RETURN TO CALLER 2876 <1> 2877 <1> ; 24/07/2022 2878 <1> %if 0 2879 <1> ;----- SET TYPAMATIC RATE AND DELAY 2880 <1> _K300: 2881 <1> cmp al, 5 ; CORRECT FUNCTION CALL? 2882 <1> jne short _KIO_EXIT ; NO, RETURN 2883 <1> test bl, 0E0h ; TEST FOR OUT-OF-RANGE RATE 2884 <1> jnz short _KIO_EXIT ; RETURN IF SO 2885 <1> test BH, 0FCh ; TEST FOR OUT-OF-RANGE DELAY 2886 <1> jnz short _KIO_EXIT ; RETURN IF SO 2887 <1> mov al, KB_TYPA_RD ; COMMAND FOR TYPAMATIC RATE/DELAY 2888 <1> call SND_DATA ; SEND TO KEYBOARD 2889 <1> ;mov cx, 5 ; SHIFT COUNT 2890 <1> ;shl bh, cl ; SHIFT DELAY OVER 2891 <1> shl bh, 5 2892 <1> mov al, bl ; PUT IN RATE 2893 <1> or al, bh ; AND DELAY 2894 <1> call SND_DATA ; SEND TO KEYBOARD 2895 <1> jmp _KIO_EXIT ; RETURN TO CALLER 2896 <1> 2897 <1> ;----- WRITE TO KEYBOARD BUFFER 2898 <1> _K500: 2899 <1> push esi ; SAVE SI (esi) 2900 <1> cli ; 2901 <1> mov ebx, [BUFFER_TAIL] ; GET THE 'IN TO' POINTER TO THE BUFFER 2902 <1> mov esi, ebx ; SAVE A COPY IN CASE BUFFER NOT FULL 2903 <1> call _K4 ; BUMP THE POINTER TO SEE IF BUFFER IS FULL 2904 <1> cmp ebx, [BUFFER_HEAD] ; WILL THE BUFFER OVERRUN IF WE STORE THIS? 2905 <1> je short _K502 ; YES - INFORM CALLER OF ERROR 2906 <1> mov [esi], cx ; NO - PUT ASCII/SCAN CODE INTO BUFFER 2907 <1> mov [BUFFER_TAIL], ebx ; ADJUST 'IN TO' POINTER TO REFLECT CHANGE 2908 <1> sub al, al ; TELL CALLER THAT OPERATION WAS SUCCESSFUL 2909 <1> jmp short _K504 ; SUB INSTRUCTION ALSO RESETS CARRY FLAG 2910 <1> _K502: 2911 <1> mov al, 01h ; BUFFER FULL INDICATION 2912 <1> _K504: 2913 <1> sti 2914 <1> pop esi ; RECOVER SI (esi) 2915 <1> jmp _KIO_EXIT ; RETURN TO CALLER WITH STATUS IN AL 2916 <1> %endif 2917 <1> 2918 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS ----- 2919 <1> _KIO_E_XLAT: 2920 00000BE2 3CF0 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2921 00000BE4 7506 <1> jne short _KIO_E_RET ; NO, PASS IT ON 2922 00000BE6 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2923 00000BE8 7402 <1> jz short _KIO_E_RET ; PASS THIS ON UNCHANGED 2924 00000BEA 30C0 <1> xor al, al ; OTHERWISE SET AL = 0 2925 <1> _KIO_E_RET: 2926 00000BEC C3 <1> retn ; GO BACK 2927 <1> 2928 <1> ;----- READ THE KEY TO FIGURE OUT WHAT TO DO ----- 2929 <1> _K1S: 2930 00000BED FA <1> cli ; 03/12/2014 2931 00000BEE 8B1D[D0610000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2932 00000BF4 3B1D[D4610000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2933 <1> ;jne short _K1U ; IF ANYTHING IN BUFFER SKIP INTERRUPT 2934 00000BFA 750F <1> jne short _k1x ; 03/12/2014 2935 <1> ; 2936 <1> ; 03/12/2014 2937 <1> ; 28/08/2014 2938 <1> ; PERFORM OTHER FUNCTION ?? here ! 2939 <1> ;;mov ax, 9002h ; MOVE IN WAIT CODE & TYPE 2940 <1> ;;int 15h ; PERFORM OTHER FUNCTION 2941 <1> _K1T: ; ASCII READ 2942 00000BFC FB <1> sti ; INTERRUPTS BACK ON DURING LOOP 2943 00000BFD 90 <1> nop ; ALLOW AN INTERRUPT TO OCCUR 2944 <1> _K1U: 2945 00000BFE FA <1> cli ; INTERRUPTS BACK OFF 2946 00000BFF 8B1D[D0610000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2947 00000C05 3B1D[D4610000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2948 <1> _k1x: 2949 00000C0B 53 <1> push ebx ; SAVE ADDRESS 2950 00000C0C 9C <1> pushf ; SAVE FLAGS 2951 00000C0D E895060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2952 00000C12 8A1D[C5610000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2953 00000C18 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2954 00000C1A 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2955 00000C1D 7406 <1> jz short _K1V ; IF NO CHANGE BYPASS UPDATE 2956 00000C1F E82F060000 <1> call SND_LED1 2957 00000C24 FA <1> cli ; DISABLE INTERRUPTS 2958 <1> _K1V: 2959 00000C25 9D <1> popf ; RESTORE FLAGS 2960 00000C26 5B <1> pop ebx ; RESTORE ADDRESS 2961 00000C27 74D3 <1> je short _K1T ; LOOP UNTIL SOMETHING IN BUFFER 2962 <1> ; 2963 00000C29 668B03 <1> mov ax, [ebx] ; GET SCAN CODE AND ASCII CODE 2964 00000C2C E834000000 <1> call _K4 ; MOVE POINTER TO NEXT POSITION 2965 00000C31 891D[D0610000] <1> mov [BUFFER_HEAD], ebx ; STORE VALUE IN VARIABLE 2966 00000C37 C3 <1> retn ; RETURN 2967 <1> 2968 <1> ;----- READ THE KEY TO SEE IF ONE IS PRESENT ----- 2969 <1> _K2S: 2970 00000C38 FA <1> cli ; INTERRUPTS OFF 2971 00000C39 8B1D[D0610000] <1> mov ebx, [BUFFER_HEAD] ; GET HEAD POINTER 2972 00000C3F 3B1D[D4610000] <1> cmp ebx, [BUFFER_TAIL] ; IF EQUAL (Z=1) THEN NOTHING THERE 2973 00000C45 668B03 <1> mov ax, [ebx] 2974 00000C48 9C <1> pushf ; SAVE FLAGS 2975 <1> ;push ax ; SAVE CODE 2976 <1> ; 24/12/2021 2977 00000C49 50 <1> push eax 2978 00000C4A E858060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2979 00000C4F 8A1D[C5610000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2980 00000C55 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2981 00000C57 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2982 00000C5A 7405 <1> jz short _K2T ; IF NO CHANGE BYPASS UPDATE 2983 00000C5C E8DB050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2984 <1> _K2T: 2985 <1> ;pop ax ; RESTORE CODE 2986 <1> ; 24/12/2021 2987 00000C61 58 <1> pop eax 2988 00000C62 9D <1> popf ; RESTORE FLAGS 2989 00000C63 FB <1> sti ; INTERRUPTS BACK ON 2990 00000C64 C3 <1> retn ; RETURN 2991 <1> 2992 <1> ; 24/07/2022 2993 <1> %if 0 2994 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS ----- 2995 <1> _KIO_S_XLAT: 2996 <1> cmp ah, 0E0h ; IS IT KEYPAD ENTER OR / ? 2997 <1> jne short _KIO_S2 ; NO, CONTINUE 2998 <1> cmp al, 0Dh ; KEYPAD ENTER CODE? 2999 <1> je short _KIO_S1 ; YES, MASSAGE A BIT 3000 <1> cmp al, 0Ah ; CTRL KEYPAD ENTER CODE? 3001 <1> je short _KIO_S1 ; YES, MASSAGE THE SAME 3002 <1> mov ah, 35h ; NO, MUST BE KEYPAD / 3003 <1> _kio_ret: ; 03/12/2014 3004 <1> clc 3005 <1> retn 3006 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 3007 <1> _KIO_S1: 3008 <1> mov ah, 1Ch ; CONVERT TO COMPATIBLE OUTPUT 3009 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 3010 <1> retn 3011 <1> _KIO_S2: 3012 <1> cmp ah, 84h ; IS IT ONE OF EXTENDED ONES? 3013 <1> ja short _KIO_DIS ; YES, THROW AWAY AND GET ANOTHER CHAR 3014 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 3015 <1> jne short _KIO_S3 ; NO, TRY LAST TEST 3016 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 3017 <1> jz short _KIO_USE ; PASS THIS ON UNCHANGED 3018 <1> jmp short _KIO_DIS ; THROW AWAY THE REST 3019 <1> _KIO_S3: 3020 <1> cmp al, 0E0h ; IS IT AN EXTENSION OF A PREVIOUS ONE? 3021 <1> ;jne short _KIO_USE ; NO, MUST BE A STANDARD CODE 3022 <1> jne short _kio_ret 3023 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 3024 <1> jz short _KIO_USE ; JUMP IF AH = 0 3025 <1> xor al, al ; CONVERT TO COMPATIBLE OUTPUT 3026 <1> ;jmp short _KIO_USE ; PASS IT ON TO CALLER 3027 <1> _KIO_USE: 3028 <1> ;clc ; CLEAR CARRY TO INDICATE GOOD CODE 3029 <1> retn ; RETURN 3030 <1> _KIO_DIS: 3031 <1> stc ; SET CARRY TO INDICATE DISCARD CODE 3032 <1> retn ; RETURN 3033 <1> 3034 <1> %endif 3035 <1> 3036 <1> ;----- INCREMENT BUFFER POINTER ROUTINE ----- 3037 <1> _K4: 3038 00000C65 43 <1> inc ebx 3039 00000C66 43 <1> inc ebx ; MOVE TO NEXT WORD IN LIST 3040 00000C67 3B1D[CC610000] <1> cmp ebx, [BUFFER_END] ; AT END OF BUFFER? 3041 <1> ;jne short _K5 ; NO, CONTINUE 3042 00000C6D 7206 <1> jb short _K5 3043 00000C6F 8B1D[C8610000] <1> mov ebx, [BUFFER_START] ; YES, RESET TO BUFFER BEGINNING 3044 <1> _K5: 3045 00000C75 C3 <1> retn 3046 <1> 3047 <1> ; 20/02/2015 3048 <1> ; 05/12/2014 3049 <1> ; 26/08/2014 3050 <1> ; KEYBOARD (HARDWARE) INTERRUPT - IRQ LEVEL 1 3051 <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014) 3052 <1> ; 3053 <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 3054 <1> ; rombios source code (06/10/1985) 3055 <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1) 3056 <1> 3057 <1> ;--------- 8042 COMMANDS ------------------------------------------------------- 3058 <1> ENA_KBD equ 0AEh ; ENABLE KEYBOARD COMMAND 3059 <1> DIS_KBD equ 0ADh ; DISABLE KEYBOARD COMMAND 3060 <1> SHUT_CMD equ 0FEh ; CAUSE A SHUTDOWN COMMAND 3061 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 3062 <1> STATUS_PORT equ 064h ; 8042 STATUS PORT 3063 <1> INPT_BUF_FULL equ 00000010b ; 1 = +INPUT BUFFER FULL 3064 <1> PORT_A equ 060h ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 3065 <1> ;---------- 8042 KEYBOARD RESPONSE --------------------------------------------- 3066 <1> KB_ACK equ 0FAh ; ACKNOWLEDGE PROM TRANSMISSION 3067 <1> KB_RESEND equ 0FEh ; RESEND REQUEST 3068 <1> KB_OVER_RUN equ 0FFh ; OVER RUN SCAN CODE 3069 <1> ;---------- KEYBOARD/LED COMMANDS ---------------------------------------------- 3070 <1> KB_ENABLE equ 0F4h ; KEYBOARD ENABLE 3071 <1> LED_CMD equ 0EDh ; LED WRITE COMMAND 3072 <1> KB_TYPA_RD equ 0F3h ; TYPAMATIC RATE/DELAY COMMAND 3073 <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------ 3074 <1> NUM_KEY equ 69 ; SCAN CODE FOR NUMBER LOCK KEY 3075 <1> SCROLL_KEY equ 70 ; SCAN CODE FOR SCROLL LOCK KEY 3076 <1> ALT_KEY equ 56 ; SCAN CODE FOR ALTERNATE SHIFT KEY 3077 <1> CTL_KEY equ 29 ; SCAN CODE FOR CONTROL KEY 3078 <1> CAPS_KEY equ 58 ; SCAN CODE FOR SHIFT LOCK KEY 3079 <1> DEL_KEY equ 83 ; SCAN CODE FOR DELETE KEY 3080 <1> INS_KEY equ 82 ; SCAN CODE FOR INSERT KEY 3081 <1> LEFT_KEY equ 42 ; SCAN CODE FOR LEFT SHIFT 3082 <1> RIGHT_KEY equ 54 ; SCAN CODE FOR RIGHT SHIFT 3083 <1> SYS_KEY equ 84 ; SCAN CODE FOR SYSTEM KEY 3084 <1> ;---------- ENHANCED KEYBOARD SCAN CODES --------------------------------------- 3085 <1> ID_1 equ 0ABh ; 1ST ID CHARACTER FOR KBX 3086 <1> ID_2 equ 041h ; 2ND ID CHARACTER FOR KBX 3087 <1> ID_2A equ 054h ; ALTERNATE 2ND ID CHARACTER FOR KBX 3088 <1> F11_M equ 87 ; F11 KEY MAKE 3089 <1> F12_M equ 88 ; F12 KEY MAKE 3090 <1> MC_E0 equ 224 ; GENERAL MARKER CODE 3091 <1> MC_E1 equ 225 ; PAUSE KEY MARKER CODE 3092 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG---------------------------------------- 3093 <1> RIGHT_SHIFT equ 00000001b ; RIGHT SHIFT KEY DEPRESSED 3094 <1> LEFT_SHIFT equ 00000010b ; LEFT SHIFT KEY DEPRESSED 3095 <1> CTL_SHIFT equ 00000100b ; CONTROL SHIFT KEY DEPRESSED 3096 <1> ALT_SHIFT equ 00001000b ; ALTERNATE SHIFT KEY DEPRESSED 3097 <1> SCROLL_STATE equ 00010000b ; SCROLL LOCK STATE IS ACTIVE 3098 <1> NUM_STATE equ 00100000b ; NUM LOCK STATE IS ACTIVE 3099 <1> CAPS_STATE equ 01000000b ; CAPS LOCK STATE IS ACTIVE 3100 <1> INS_STATE equ 10000000b ; INSERT STATE IS ACTIVE 3101 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG_1 ------------------------------------- 3102 <1> L_CTL_SHIFT equ 00000001b ; LEFT CTL KEY DOWN 3103 <1> L_ALT_SHIFT equ 00000010b ; LEFT ALT KEY DOWN 3104 <1> SYS_SHIFT equ 00000100b ; SYSTEM KEY DEPRESSED AND HELD 3105 <1> HOLD_STATE equ 00001000b ; SUSPEND KEY HAS BEEN TOGGLED 3106 <1> SCROLL_SHIFT equ 00010000b ; SCROLL LOCK KEY IS DEPRESSED 3107 <1> NUM_SHIFT equ 00100000b ; NUM LOCK KEY IS DEPRESSED 3108 <1> CAPS_SHIFT equ 01000000b ; CAPS LOCK KEY IS DEPRE55ED 3109 <1> INS_SHIFT equ 10000000b ; INSERT KEY IS DEPRESSED 3110 <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 ----------------------------------- 3111 <1> KB_LEDS equ 00000111b ; KEYBOARD LED STATE BITS 3112 <1> ; equ 00000001b ; SCROLL LOCK INDICATOR 3113 <1> ; equ 00000010b ; NUM LOCK INDICATOR 3114 <1> ; equ 00000100b ; CAPS LOCK INDICATOR 3115 <1> ; equ 00001000b ; RESERVED (MUST BE ZERO) 3116 <1> KB_FA equ 00010000b ; ACKNOWLEDGMENT RECEIVED 3117 <1> KB_FE equ 00100000b ; RESEND RECEIVED FLAG 3118 <1> KB_PR_LED equ 01000000b ; MODE INDICATOR UPDATE 3119 <1> KB_ERR equ 10000000b ; KEYBOARD TRANSMIT ERROR FLAG 3120 <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 ----------------------------------- 3121 <1> LC_E1 equ 00000001b ; LAST CODE WAS THE E1 HIDDEN CODE 3122 <1> LC_E0 equ 00000010b ; LAST CODE WAS THE E0 HIDDEN CODE 3123 <1> R_CTL_SHIFT equ 00000100b ; RIGHT CTL KEY DOWN 3124 <1> R_ALT_SHIFT equ 00001000b ; RIGHT ALT KEY DOWN 3125 <1> GRAPH_ON equ 00001000b ; ALT GRAPHICS KEY DOWN (WT ONLY) 3126 <1> KBX equ 00010000b ; ENHANCED KEYBOARD INSTALLED 3127 <1> SET_NUM_LK equ 00100000b ; FORCE NUM LOCK IF READ ID AND KBX 3128 <1> LC_AB equ 01000000b ; LAST CHARACTER WAS FIRST ID CHARACTER 3129 <1> RD_ID equ 10000000b ; DOING A READ ID (MUST BE BIT0) 3130 <1> ; 3131 <1> ;----------- INTERRUPT EQUATES ------------------------------------------------- 3132 <1> EOI equ 020h ; END OF INTERRUPT COMMAND TO 8259 3133 <1> INTA00 equ 020h ; 8259 PORT 3134 <1> 3135 <1> 3136 <1> kb_int: 3137 <1> 3138 <1> ; 11/06/2022 3139 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 3140 <1> ; 17/10/2015 ('ctrlbrk') 3141 <1> ; 05/12/2014 3142 <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 3143 <1> ; instead of pc-at bios - 1985-) 3144 <1> ; 26/08/2014 3145 <1> ; 3146 <1> ; 03/06/86 KEYBOARD BIOS 3147 <1> ; 3148 <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------ 3149 <1> ; ; 3150 <1> ; KEYBOARD INTERRUPT ROUTINE ; 3151 <1> ; ; 3152 <1> ;-------------------------------------------------------------------------------- 3153 <1> 3154 <1> KB_INT_1: 3155 00000C76 FB <1> sti ; ENABLE INTERRUPTS 3156 <1> ;push ebp 3157 00000C77 50 <1> push eax 3158 00000C78 53 <1> push ebx 3159 00000C79 51 <1> push ecx 3160 00000C7A 52 <1> push edx 3161 00000C7B 56 <1> push esi 3162 00000C7C 57 <1> push edi 3163 00000C7D 1E <1> push ds 3164 00000C7E 06 <1> push es 3165 00000C7F FC <1> cld ; FORWARD DIRECTION 3166 00000C80 66B81000 <1> mov ax, KDATA 3167 00000C84 8ED8 <1> mov ds, ax 3168 00000C86 8EC0 <1> mov es, ax 3169 <1> ; 3170 <1> ;----- WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED 3171 00000C88 B0AD <1> mov al, DIS_KBD ; DISABLE THE KEYBOARD COMMAND 3172 00000C8A E852050000 <1> call SHIP_IT ; EXECUTE DISABLE 3173 00000C8F FA <1> cli ; DISABLE INTERRUPTS 3174 00000C90 B900000100 <1> mov ecx, 10000h ; SET MAXIMUM TIMEOUT 3175 <1> KB_INT_01: 3176 00000C95 E464 <1> in al, STATUS_PORT ; READ ADAPTER STATUS 3177 00000C97 A802 <1> test al, INPT_BUF_FULL ; CHECK INPUT BUFFER FULL STATUS BIT 3178 00000C99 E0FA <1> loopnz KB_INT_01 ; WAIT FOR COMMAND TO BE ACCEPTED 3179 <1> ; 3180 <1> ;----- READ CHARACTER FROM KEYBOARD INTERFACE 3181 00000C9B E460 <1> in al, PORT_A ; READ IN THE CHARACTER 3182 <1> ; 3183 <1> ;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 3184 <1> ;MOV AH, 04FH ; SYSTEM INTERCEPT - KEY CODE FUNCTION 3185 <1> ;STC ; SET CY=1 (IN CASE OF IRET) 3186 <1> ;INT 15H ; CASETTE CALL (AL)=KEY SCAN CODE 3187 <1> ; ; RETURNS CY=1 FOR INVALID FUNCTION 3188 <1> ;JC KB_INT_02 ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) 3189 <1> ;JMP K26 ; EXIT IF SYSTEM HANDLES SCAN CODE 3190 <1> ; ; EXÝT HANDLES HARDWARE EOI AND ENABLE 3191 <1> ; 3192 <1> ;----- CHECK FOR A RESEND COMMAND TO KEYBOARD 3193 <1> KB_INT_02: ; (AL)= SCAN CODE 3194 00000C9D FB <1> sti ; ENABLE INTERRUPTS AGAIN 3195 00000C9E 3CFE <1> cmp al, KB_RESEND ; IS THE INPUT A RESEND 3196 00000CA0 7411 <1> je short KB_INT_4 ; GO IF RESEND 3197 <1> ; 3198 <1> ;----- CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD 3199 00000CA2 3CFA <1> cmp al, KB_ACK ; IS THE INPUT AN ACKNOWLEDGE 3200 00000CA4 751A <1> jne short KB_INT_2 ; GO IF NOT 3201 <1> ; 3202 <1> ;----- A COMMAND TO THE KEYBOARD WAS ISSUED 3203 00000CA6 FA <1> cli ; DISABLE INTERRUPTS 3204 00000CA7 800D[C5610000]10 <1> or byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED 3205 00000CAE E963020000 <1> jmp K26 ; RETURN IF NOT (ACK RETURNED FOR DATA) 3206 <1> ; 3207 <1> ;----- RESEND THE LAST BYTE 3208 <1> KB_INT_4: 3209 00000CB3 FA <1> cli ; DISABLE INTERRUPTS 3210 00000CB4 800D[C5610000]20 <1> or byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED 3211 00000CBB E956020000 <1> jmp K26 ; RETURN IF NOT ACK RETURNED FOR DATA) 3212 <1> ; 3213 <1> ;----- UPDATE MODE INDICATORS IF CHANGE IN STATE 3214 <1> KB_INT_2: 3215 <1> ;push ax ; SAVE DATA IN 3216 <1> ; 05/12/2021 3217 00000CC0 50 <1> push eax 3218 00000CC1 E8E1050000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 3219 00000CC6 8A1D[C5610000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 3220 00000CCC 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 3221 00000CCE 80E307 <1> and bl, KB_LEDS ; ISOLATE INDICATOR BITS 3222 00000CD1 7405 <1> jz short UP0 ; IF NO CHANGE BYPASS UPDATE 3223 00000CD3 E864050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 3224 <1> UP0: 3225 <1> ;pop ax ; RESTORE DATA IN 3226 <1> ; 05/12/2021 3227 00000CD8 58 <1> pop eax 3228 <1> ;------------------------------------------------------------------------ 3229 <1> ; START OF KEY PROCESSING ; 3230 <1> ;------------------------------------------------------------------------ 3231 00000CD9 88C4 <1> mov ah, al ; SAVE SCAN CODE IN AH ALSO 3232 <1> ; 3233 <1> ;----- TEST FOR OVERRUN SCAN CODE FROM KEYBOARD 3234 00000CDB 3CFF <1> cmp al, KB_OVER_RUN ; IS THIS AN OVERRUN CHAR 3235 <1> ;je K62 ; BUFFER_FULL_BEEP 3236 <1> ; 05/12/2021 3237 00000CDD 7505 <1> jne short K16 3238 00000CDF E9E9040000 <1> jmp K62 3239 <1> K16: 3240 00000CE4 8A3D[C6610000] <1> mov bh, [KB_FLAG_3] ; LOAD FLAGS FOR TESTING 3241 <1> ; 3242 <1> ;----- TEST TO SEE IF A READ_ID IS IN PROGRESS 3243 00000CEA F6C7C0 <1> test bh, RD_ID+LC_AB ; ARE WE DOING A READ ID? 3244 00000CED 7442 <1> jz short NOT_ID ; CONTINUE IF NOT 3245 00000CEF 7914 <1> jns short TST_ID_2 ; IS THE RD_ID FLAG ON? 3246 00000CF1 3CAB <1> cmp al, ID_1 ; IS THIS THE 1ST ID CHARACTER? 3247 00000CF3 7507 <1> jne short RST_RD_ID 3248 00000CF5 800D[C6610000]40 <1> or byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK 3249 <1> RST_RD_ID: 3250 00000CFC 8025[C6610000]7F <1> and byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG 3251 00000D03 EB27 <1> jmp short ID_EX ; AND EXIT 3252 <1> ; 05/12/2021 3253 <1> ;jmp K26 3254 <1> ; 3255 <1> TST_ID_2: 3256 00000D05 8025[C6610000]BF <1> and byte [KB_FLAG_3], ~LC_AB ; RESET FLAG 3257 00000D0C 3C54 <1> cmp al, ID_2A ; IS THIS THE 2ND ID CHARACTER? 3258 00000D0E 7415 <1> je short KX_BIT ; JUMP IF SO 3259 00000D10 3C41 <1> cmp al, ID_2 ; IS THIS THE 2ND ID CHARACTER? 3260 00000D12 7518 <1> jne short ID_EX ; LEAVE IF NOT 3261 <1> ; 05/12/2021 3262 <1> ;jne K26 3263 <1> ; 3264 <1> ;----- A READ ID SAID THAT IT WAS ENHANCED KEYBOARD 3265 00000D14 F6C720 <1> test bh, SET_NUM_LK ; SHOULD WE SET NUM LOCK? 3266 00000D17 740C <1> jz short KX_BIT ; EXIT IF NOT 3267 00000D19 800D[C3610000]20 <1> or byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON 3268 00000D20 E817050000 <1> call SND_LED ; GO SET THE NUM LOCK INDICATOR 3269 <1> KX_BIT: 3270 00000D25 800D[C6610000]10 <1> or byte [KB_FLAG_3], KBX ; INDICATE ENHANCED KEYBOARD WAS FOUND 3271 00000D2C E9E5010000 <1> ID_EX: jmp K26 ; EXIT 3272 <1> ; 3273 <1> NOT_ID: 3274 00000D31 3CE0 <1> cmp al, MC_E0 ; IS THIS THE GENERAL MARKER CODE? 3275 00000D33 750E <1> jne short TEST_E1 3276 00000D35 800D[C6610000]12 <1> or byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND 3277 00000D3C EB10 <1> jmp short EXIT ; THROW AWAY THIS CODE 3278 <1> ; 05/12/2021 3279 00000D3E E9DA010000 <1> jmp K26A 3280 <1> TEST_E1: 3281 00000D43 3CE1 <1> cmp al, MC_E1 ; IS THIS THE PAUSE KEY? 3282 00000D45 750C <1> jne short NOT_HC 3283 00000D47 800D[C6610000]11 <1> or byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND 3284 00000D4E E9CA010000 <1> EXIT: jmp K26A ; THROW AWAY THIS CODE 3285 <1> ; 3286 <1> NOT_HC: 3287 00000D53 247F <1> and al, 07Fh ; TURN OFF THE BREAK BIT 3288 00000D55 F6C702 <1> test bh, LC_E0 ; LAST CODE THE E0 MARKER CODE 3289 00000D58 740D <1> jz short NOT_LC_E0 ; JUMP IF NOT 3290 <1> ; 3291 00000D5A BF[AE600000] <1> mov edi, _K6+6 ; IS THIS A SHIFT KEY? 3292 00000D5F AE <1> scasb 3293 <1> ;je K26 ; K16B ; YES, THROW AWAY & RESET FLAG 3294 <1> ; 05/12/2021 3295 00000D60 7458 <1> je short K16B 3296 00000D62 AE <1> scasb 3297 00000D63 756A <1> jne short K16A ; NO, CONTINUE KEY PROCESSING 3298 00000D65 EB53 <1> jmp short K16B ; YES, THROW AWAY & RESET FLAG 3299 <1> ; 05/12/2021 3300 <1> ;jmp K26 3301 <1> ; 3302 <1> NOT_LC_E0: 3303 00000D67 F6C701 <1> test bh, LC_E1 ; LAST CODE THE E1 MARKER CODE? 3304 00000D6A 7425 <1> jz short T_SYS_KEY ; JUMP IF NOT 3305 00000D6C B904000000 <1> mov ecx, 4 ; LENGHT OF SEARCH 3306 00000D71 BF[AC600000] <1> mov edi, _K6+4 ; IS THIS AN ALT, CTL, OR SHIFT? 3307 00000D76 F2AE <1> repne scasb ; CHECK IT 3308 00000D78 74D4 <1> je short EXIT ; THROW AWAY IF SO 3309 <1> ; 05/12/2021 3310 <1> ;je K26A 3311 <1> ; 3312 00000D7A 3C45 <1> cmp al, NUM_KEY ; IS IT THE PAUSE KEY? 3313 00000D7C 753C <1> jne short K16B ; NO, THROW AWAY & RESET FLAG 3314 <1> ; 05/12/2021 3315 <1> ;jne K26 3316 00000D7E F6C480 <1> test ah, 80h ; YES, IS IT THE BREAK OF THE KEY? 3317 00000D81 7537 <1> jnz short K16B ; YES, THROW THIS AWAY, TOO 3318 <1> ; 05/12/2021 3319 <1> ;jnz K26 3320 <1> ; 20/02/2015 3321 00000D83 F605[C4610000]08 <1> test byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY? 3322 00000D8A 752E <1> jnz short K16B ; YES, THROW AWAY 3323 <1> ; 05/12/2021 3324 <1> ;jnz K26 3325 00000D8C E9D2020000 <1> jmp K39P ; NO, THIS IS THE REAL PAUSE STATE 3326 <1> ; 3327 <1> ;----- TEST FOR SYSTEM KEY 3328 <1> T_SYS_KEY: 3329 00000D91 3C54 <1> cmp al, SYS_KEY ; IS IT THE SYSTEM KEY? 3330 00000D93 753A <1> jnz short K16A ; CONTINUE IF NOT 3331 <1> ; 3332 00000D95 F6C480 <1> test ah, 80h ; CHECK IF THIS A BREAK CODE 3333 00000D98 7525 <1> jnz short K16C ; DO NOT TOUCH SYSTEM INDICATOR IF TRUE 3334 <1> ; 3335 00000D9A F605[C4610000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 3336 00000DA1 7517 <1> jnz short K16B ; IF YES, DO NOT PROCESS SYSTEM INDICATOR 3337 <1> ;jnz K26 3338 <1> ; 3339 00000DA3 800D[C4610000]04 <1> or byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED 3340 00000DAA B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3341 00000DAC E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3342 <1> ; INTERRUPT-RETURN-NO-EOI 3343 00000DAE B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3344 00000DB0 E82C040000 <1> call SHIP_IT ; EXECUTE ENABLE 3345 <1> ; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!! 3346 <1> ;mov al, 8500h ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY 3347 <1> ;sti ; MAKE SURE INTERRUPTS ENABLED 3348 <1> ;int 15h ; USER INTERRUPT 3349 00000DB5 E96F010000 <1> jmp K27A ; END PROCESSING 3350 <1> ; 3351 00000DBA E957010000 <1> K16B: jmp K26 ; IGNORE SYSTEM KEY 3352 <1> ; 3353 <1> K16C: 3354 00000DBF 8025[C4610000]FB <1> and byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN 3355 00000DC6 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3356 00000DC8 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3357 <1> ; INTERRUPT-RETURN-NO-EOI 3358 <1> ;mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3359 <1> ;call SHIP_IT ; EXECUTE ENABLE 3360 <1> ; 3361 <1> ;mov ax, 8501h ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY 3362 <1> ;sti ; MAKE SURE INTERRUPTS ENABLED 3363 <1> ;int 15h ; USER INTERRUPT 3364 <1> ;jmp K27A ; IGNORE SYSTEM KEY 3365 <1> ; 3366 00000DCA E953010000 <1> jmp K27 ; IGNORE SYSTEM KEY 3367 <1> ; 3368 <1> ;----- TEST FOR SHIFT KEYS 3369 <1> K16A: 3370 00000DCF 8A1D[C3610000] <1> mov bl, [KB_FLAG] ; PUT STATE FLAGS IN BL 3371 00000DD5 BF[A8600000] <1> mov edi, _K6 ; SHIFT KEY TABLE offset 3372 00000DDA B908000000 <1> mov ecx, _K6L ; LENGTH 3373 00000DDF F2AE <1> repne scasb ; LOOK THROUGH THE TABLE FOR A MATCH 3374 00000DE1 88E0 <1> mov al, ah ; RECOVER SCAN CODE 3375 <1> ;jne K25 ; IF NO MATCH, THEN SHIFT NOT FOUND 3376 <1> ; 05/12/2021 3377 00000DE3 7405 <1> je short K17 3378 00000DE5 E914010000 <1> jmp K25 3379 <1> ; 3380 <1> ;------ SHIFT KEY FOUND 3381 <1> K17: 3382 00000DEA 81EF[A9600000] <1> sub edi, _K6+1 ; ADJUST PTR TO SCAN CODE MATCH 3383 00000DF0 8AA7[B0600000] <1> mov ah, [edi+_K7] ; GET MASK INTO AH 3384 00000DF6 B102 <1> mov cl, 2 ; SETUP COUNT FOR FLAG SHIFTS 3385 00000DF8 A880 <1> test al, 80h ; TEST FOR BREAK KEY 3386 <1> ;jnz K23 ; JUMP OF BREAK 3387 <1> ; 05/12/2021 3388 00000DFA 7405 <1> jz short K17C 3389 00000DFC E999000000 <1> jmp K23 3390 <1> ; 3391 <1> ;----- SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE 3392 <1> K17C: 3393 00000E01 80FC10 <1> cmp ah, SCROLL_SHIFT 3394 00000E04 732C <1> jae short K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY 3395 <1> ; 3396 <1> ;----- PLAIN SHIFT KEY, SET SHIFT ON 3397 00000E06 0825[C3610000] <1> or [KB_FLAG], ah ; TURN ON SHIFT BIT 3398 00000E0C A80C <1> test al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL? 3399 00000E0E 7505 <1> jnz short K17D ; YES, MORE FLAGS TO SET 3400 <1> ;jz K26 ; NO, INTERRUPT RETURN 3401 <1> ; 05/12/2021 3402 00000E10 E901010000 <1> jmp K26 3403 <1> K17D: 3404 00000E15 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF NEW KEYS? 3405 00000E18 740B <1> jz short K17E ; NO, JUMP 3406 00000E1A 0825[C6610000] <1> or [KB_FLAG_3], ah ; SET BITS FOR RIGHT CTRL, ALT 3407 00000E20 E9F1000000 <1> jmp K26 ; INTERRUPT RETURN 3408 <1> K17E: 3409 00000E25 D2EC <1> shr ah, cl ; MOVE FLAG BITS TWO POSITIONS 3410 00000E27 0825[C4610000] <1> or [KB_FLAG_1], ah ; SET BITS FOR LEFT CTRL, ALT 3411 00000E2D E9E4000000 <1> jmp K26 3412 <1> ; 3413 <1> ;----- TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT 3414 <1> K18: ; SHIFT-TOGGLE 3415 00000E32 F6C304 <1> test bl, CTL_SHIFT ; CHECK CTL SHIFT STATE 3416 00000E35 7405 <1> jz short K18A ; JUMP IF NOT CTL STATE 3417 <1> ;jnz K25 ; JUMP IF CTL STATE 3418 <1> ; 05/12/2021 3419 00000E37 E9C2000000 <1> jmp K25 3420 <1> K18A: 3421 00000E3C 3C52 <1> cmp al, INS_KEY ; CHECK FOR INSERT KEY 3422 00000E3E 7525 <1> jne short K22 ; JUMP IF NOT INSERT KEY 3423 00000E40 F6C308 <1> test bl, ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT 3424 00000E43 7405 <1> jz short K18B ; JUMP IF NOT ALTERNATE SHIFT 3425 <1> ;jnz K25 ; JUMP IF ALTERNATE SHIFT 3426 <1> ; 05/12/2021 3427 00000E45 E9B4000000 <1> jmp K25 3428 <1> K18B: 3429 00000E4A F6C702 <1> test bh, LC_E0 ;20/02/2015 ; IS THIS NEW INSERT KEY? 3430 00000E4D 7516 <1> jnz short K22 ; YES, THIS ONE'S NEVER A '0' 3431 <1> K19: 3432 00000E4F F6C320 <1> test bl, NUM_STATE ; CHECK FOR BASE STATE 3433 00000E52 750C <1> jnz short K21 ; JUMP IF NUM LOCK IS ON 3434 00000E54 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE 3435 00000E57 740C <1> jz short K22 ; JUMP IF BASE STATE 3436 <1> K20: ; NUMERIC ZERO, NOT INSERT KEY 3437 00000E59 88C4 <1> mov ah, al ; PUT SCAN CODE BACK IN AH 3438 00000E5B E99E000000 <1> jmp K25 ; NUMERAL '0', STNDRD. PROCESSING 3439 <1> K21: ; MIGHT BE NUMERIC 3440 00000E60 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 3441 00000E63 74F4 <1> jz short K20 ; IS NUMERIC, STD. PROC. 3442 <1> ; 3443 <1> K22: ; SHIFT TOGGLE KEY HIT; PROCESS IT 3444 00000E65 8425[C4610000] <1> test ah, [KB_FLAG_1] ; IS KEY ALREADY DEPRESSED 3445 <1> ;jnz K26 3446 <1> ; 05/12/2021 3447 00000E6B 7405 <1> jz short K22A 3448 00000E6D E9A4000000 <1> jmp K26 ; JUMP IF KEY ALREADY DEPRESSED 3449 <1> K22A: 3450 00000E72 0825[C4610000] <1> or [KB_FLAG_1], ah ; INDICATE THAT THE KEY IS DEPRESSED 3451 00000E78 3025[C3610000] <1> xor [KB_FLAG], ah ; TOGGLE THE SHIFT STATE 3452 <1> ; 3453 <1> ;----- TOGGLE LED IF CAPS, NUM OR SCROLL KEY DEPRESSED 3454 00000E7E F6C470 <1> test ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE? 3455 00000E81 7407 <1> jz short K22B ; GO IF NOT 3456 <1> ; 3457 <1> ; 05/12/2021 3458 <1> ;push ax ; SAVE SCAN CODE AND SHIFT MASK 3459 00000E83 50 <1> push eax 3460 00000E84 E8B3030000 <1> call SND_LED ; GO TURN MODE INDICATORS ON 3461 <1> ;pop ax ; RESTORE SCAN CODE 3462 00000E89 58 <1> pop eax 3463 <1> K22B: 3464 00000E8A 3C52 <1> cmp al, INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY 3465 <1> ;jne K26 ; JUMP IF NOT INSERT KEY 3466 <1> ; 05/12/2021 3467 00000E8C 7405 <1> je short K22C 3468 00000E8E E983000000 <1> jmp K26 ; JUMP IF NOT INSERT KEY 3469 <1> K22C: 3470 00000E93 88C4 <1> mov ah, al ; SCAN CODE IN BOTH HALVES OF AX 3471 00000E95 E999000000 <1> jmp K28 ; FLAGS UPDATED, PROC. FOR BUFFER 3472 <1> ; 3473 <1> ;----- BREAK SHIFT FOUND 3474 <1> K23: ; BREAK-SHIFT-FOUND 3475 00000E9A 80FC10 <1> cmp ah, SCROLL_SHIFT ; IS THIS A TOGGLE KEY 3476 00000E9D F6D4 <1> not ah ; INVERT MASK 3477 00000E9F 7355 <1> jae short K24 ; YES, HANDLE BREAK TOGGLE 3478 00000EA1 2025[C3610000] <1> and [KB_FLAG], ah ; TURN OFF SHIFT BIT 3479 00000EA7 80FCFB <1> cmp ah, ~CTL_SHIFT ; IS THIS ALT OR CTL? 3480 00000EAA 7730 <1> ja short K23D ; NO, ALL DONE 3481 <1> ; 3482 00000EAC F6C702 <1> test bh, LC_E0 ; 2ND ALT OR CTL? 3483 00000EAF 7408 <1> jz short K23A ; NO, HANSLE NORMALLY 3484 00000EB1 2025[C6610000] <1> and [KB_FLAG_3], ah ; RESET BIT FOR RIGHT ALT OR CTL 3485 00000EB7 EB08 <1> jmp short K23B ; CONTINUE 3486 <1> K23A: 3487 00000EB9 D2FC <1> sar ah, cl ; MOVE THE MASK BIT TWO POSITIONS 3488 00000EBB 2025[C4610000] <1> and [KB_FLAG_1], ah ; RESET BIT FOR LEFT ALT AND CTL 3489 <1> K23B: 3490 00000EC1 88C4 <1> mov ah, al ; SAVE SCAN CODE 3491 00000EC3 A0[C6610000] <1> mov al, [KB_FLAG_3] ; GET RIGHT ALT & CTRL FLAGS 3492 00000EC8 D2E8 <1> shr al, cl ; MOVE TO BITS 1 & 0 3493 00000ECA 0A05[C4610000] <1> or al, [KB_FLAG_1] ; PUT IN LEFT ALÞT & CTL FLAGS 3494 00000ED0 D2E0 <1> shl al, cl ; MOVE BACK TO BITS 3 & 2 3495 00000ED2 240C <1> and al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE 3496 00000ED4 0805[C3610000] <1> or [KB_FLAG], al ; PUT RESULT IN THE REAL FLAGS 3497 00000EDA 88E0 <1> mov al, ah 3498 <1> K23D: 3499 00000EDC 3CB8 <1> cmp al, ALT_KEY+80h ; IS THIS ALTERNATE SHIFT RELEASE 3500 00000EDE 7536 <1> jne short K26 ; INTERRUPT RETURN 3501 <1> ; 3502 <1> ;----- ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER 3503 00000EE0 A0[C7610000] <1> mov al, [ALT_INPUT] 3504 00000EE5 B400 <1> mov ah, 0 ; SCAN CODE OF 0 3505 00000EE7 8825[C7610000] <1> mov [ALT_INPUT], ah ; ZERO OUT THE FIELD 3506 00000EED 3C00 <1> cmp al, 0 ; WAS THE INPUT = 0? 3507 00000EEF 7425 <1> je short K26 ; INTERRUPT_RETURN 3508 00000EF1 E9B4020000 <1> jmp K61 ; IT WASN'T, SO PUT IN BUFFER 3509 <1> ; 3510 <1> K24: ; BREAK-TOGGLE 3511 00000EF6 2025[C4610000] <1> and [KB_FLAG_1], ah ; INDICATE NO LONGER DEPRESSED 3512 00000EFC EB18 <1> jmp short K26 ; INTERRUPT_RETURN 3513 <1> ; 3514 <1> ;----- TEST FOR HOLD STATE 3515 <1> ; AL, AH = SCAN CODE 3516 <1> K25: ; NO-SHIFT-FOUND 3517 00000EFE 3C80 <1> cmp al, 80h ; TEST FOR BREAK KEY 3518 00000F00 7314 <1> jae short K26 ; NOTHING FOR BREAK CHARS FROM HERE ON 3519 00000F02 F605[C4610000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE 3520 00000F09 7428 <1> jz short K28 ; BRANCH AROUND TEST IF NOT 3521 00000F0B 3C45 <1> cmp al, NUM_KEY 3522 00000F0D 7407 <1> je short K26 ; CAN'T END HOLD ON NUM_LOCK 3523 00000F0F 8025[C4610000]F7 <1> and byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT 3524 <1> ; 3525 <1> K26: 3526 00000F16 8025[C6610000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 3527 <1> K26A: ; INTERRUPT-RETURN 3528 00000F1D FA <1> cli ; TURN OFF INTERRUPTS 3529 00000F1E B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3530 00000F20 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3531 <1> K27: ; INTERRUPT-RETURN-NO-EOI 3532 00000F22 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3533 00000F24 E8B8020000 <1> call SHIP_IT ; EXECUTE ENABLE 3534 <1> K27A: 3535 00000F29 FA <1> cli ; DISABLE INTERRUPTS 3536 00000F2A 07 <1> pop es ; RESTORE REGISTERS 3537 00000F2B 1F <1> pop ds 3538 00000F2C 5F <1> pop edi 3539 00000F2D 5E <1> pop esi 3540 00000F2E 5A <1> pop edx 3541 00000F2F 59 <1> pop ecx 3542 00000F30 5B <1> pop ebx 3543 00000F31 58 <1> pop eax 3544 <1> ;pop ebp 3545 00000F32 CF <1> iret ; RETURN 3546 <1> 3547 <1> ;----- NOT IN HOLD STATE 3548 <1> K28: ; NO-HOLD-STATE 3549 00000F33 3C58 <1> cmp al, 88 ; TEST FOR OUT-OF-RANGE SCAN CODES 3550 00000F35 77DF <1> ja short K26 ; IGNORE IF OUT-OF-RANGE 3551 <1> ; 3552 00000F37 F6C308 <1> test bl, ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT 3553 00000F3A 740E <1> jz short K28A ; IF NOT ALTERNATE 3554 <1> ; 05/12/2021 3555 <1> ;jz K38 3556 <1> ; 3557 00000F3C F6C710 <1> test bh, KBX ; IS THIS THE ENCHANCED KEYBOARD? 3558 00000F3F 740E <1> jz short K29 ; NO, ALT STATE IS REAL 3559 <1> ; 28/02/2015 3560 00000F41 F605[C4610000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN? 3561 00000F48 7405 <1> jz short K29 ; NO, ALT STATE IS REAL 3562 <1> ; 05/12/2021 3563 <1> ;jnz K38 ; YES, THIS IS PHONY ALT STATE 3564 <1> ; ; DUE TO PRESSING SYSREQ 3565 00000F4A E9CD000000 <1> K28A: jmp K38 3566 <1> ; 3567 <1> ;----- TEST FOR RESET KEY SEQUENCE (CTL ALT DEL) 3568 <1> K29: ; TEST-RESET 3569 00000F4F F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO? 3570 00000F52 740B <1> jz short K31 ; NO_RESET 3571 00000F54 3C53 <1> cmp al, DEL_KEY ; CTL-ALT STATE, TEST FOR DELETE KEY 3572 00000F56 7507 <1> jne short K31 ; NO_RESET, IGNORE 3573 <1> ; 3574 <1> ;----- CTL-ALT-DEL HAS BEEN FOUND 3575 <1> ; 26/08/2014 3576 <1> cpu_reset: 3577 <1> ; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN) 3578 <1> ; Send FEh (system reset command) to the keyboard controller. 3579 00000F58 B0FE <1> mov al, SHUT_CMD ; SHUTDOWN COMMAND 3580 00000F5A E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROL PORT 3581 <1> khere: 3582 00000F5C F4 <1> hlt ; WAIT FOR 80286 RESET 3583 00000F5D EBFD <1> jmp short khere ; INSURE HALT 3584 <1> 3585 <1> ; 3586 <1> ;----- IN ALTERNATE SHIFT, RESET NOT FOUND 3587 <1> K31: ; NO-RESET 3588 00000F5F 3C39 <1> cmp al, 57 ; TEST FOR SPACE KEY 3589 00000F61 7507 <1> jne short K311 ; NOT THERE 3590 00000F63 B020 <1> mov al, ' ' ; SET SPACE CHAR 3591 00000F65 E932020000 <1> jmp K57 ; BUFFER_FILL 3592 <1> K311: 3593 00000F6A 3C0F <1> cmp al, 15 ; TEST FOR TAB KEY 3594 00000F6C 7509 <1> jne short K312 ; NOT THERE 3595 00000F6E 66B800A5 <1> mov ax, 0A500h ; SET SPECIAL CODE FOR ALT-TAB 3596 00000F72 E925020000 <1> jmp K57 ; BUFFER_FILL 3597 <1> K312: 3598 00000F77 3C4A <1> cmp al, 74 ; TEST FOR KEY PAD - 3599 00000F79 7471 <1> je short K37B ; GO PROCESS 3600 00000F7B 3C4E <1> cmp al, 78 ; TEST FOR KEY PAD + 3601 00000F7D 746D <1> je short K37B ; GO PROCESS 3602 <1> ; 3603 <1> ;----- LOOK FOR KEY PAD ENTRY 3604 <1> K32: ; ALT-KEY-PAD 3605 00000F7F BF[84600000] <1> mov edi, K30 ; ALT-INPUT-TABLE offset 3606 00000F84 B90A000000 <1> mov ecx, 10 ; LOOK FOR ENTRY USING KEYPAD 3607 00000F89 F2AE <1> repne scasb ; LOOK FOR MATCH 3608 00000F8B 7523 <1> jne short K33 ; NO_ALT_KEYPAD 3609 00000F8D F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF THE NEW KEYS? 3610 <1> ;jnz short K37C ; YES, JUMP, NOT NUMPAD KEY 3611 <1> ; 05/12/2021 3612 00000F90 751C <1> jnz short K32B 3613 00000F92 81EF[85600000] <1> sub edi, K30+1 ; DI NOW HAS ENTRY VALUE 3614 00000F98 A0[C7610000] <1> mov al, [ALT_INPUT] ; GET THE CURRENT BYTE 3615 00000F9D B40A <1> mov ah, 10 ; MULTIPLY BY 10 3616 00000F9F F6E4 <1> mul ah 3617 00000FA1 6601F8 <1> add ax, di ; ADD IN THE LATEST ENTRY 3618 00000FA4 A2[C7610000] <1> mov [ALT_INPUT], al ; STORE IT AWAY 3619 <1> K32A: 3620 00000FA9 E968FFFFFF <1> jmp K26 ; THROW AWAY THAT KEYSTROKE 3621 <1> K32B: 3622 <1> ; 05/12/2021 3623 00000FAE EB66 <1> jmp K37C 3624 <1> ; 3625 <1> ;----- LOOK FOR SUPERSHIFT ENTRY 3626 <1> K33: ; NO-ALT-KEYPAD 3627 00000FB0 C605[C7610000]00 <1> mov byte [ALT_INPUT], 0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT 3628 00000FB7 B91A000000 <1> mov ecx, 26 ; (DI),(ES) ALREADY POINTING 3629 00000FBC F2AE <1> repne scasb ; LOOK FOR MATCH IN ALPHABET 3630 00000FBE 744F <1> je short K37A ; MATCH FOUND, GO FILLL THE BUFFER 3631 <1> ; 3632 <1> ;----- LOOK FOR TOP ROW OF ALTERNATE SHIFT 3633 <1> K34: ; ALT-TOP-ROW 3634 00000FC0 3C02 <1> cmp al, 2 ; KEY WITH '1' ON IT 3635 00000FC2 7228 <1> jb short K37B ; MUST BE ESCAPE 3636 00000FC4 3C0D <1> cmp al, 13 ; IS IT IN THE REGION 3637 00000FC6 7705 <1> ja short K35 ; NO, ALT SOMETHING ELSE 3638 00000FC8 80C476 <1> add ah, 118 ; CONVERT PSEUDO SCAN CODE TO RANGE 3639 00000FCB EB42 <1> jmp short K37A ; GO FILL THE BUFFER 3640 <1> ; 3641 <1> ;----- TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES 3642 <1> K35: ; ALT-FUNCTION 3643 00000FCD 3C57 <1> cmp al, F11_M ; IS IT F11? 3644 00000FCF 7209 <1> jb short K35A ; 20/02/2015 ; NO, BRANCH 3645 00000FD1 3C58 <1> cmp al, F12_M ; IS IT F12? 3646 00000FD3 7705 <1> ja short K35A ; 20/02/2015 ; NO, BRANCH 3647 00000FD5 80C434 <1> add ah, 52 ; CONVERT TO PSEUDO SCAN CODE 3648 00000FD8 EB35 <1> jmp short K37A ; GO FILL THE BUFFER 3649 <1> K35A: 3650 00000FDA F6C702 <1> test bh, LC_E0 ; DO WE HAVE ONE OF THE NEW KEYS? 3651 00000FDD 7425 <1> jz short K37 ; NO, JUMP 3652 00000FDF 3C1C <1> cmp al, 28 ; TEST FOR KEYPAD ENTER 3653 00000FE1 7510 <1> jne short K35B ; NOT THERE 3654 00000FE3 66B800A6 <1> mov ax, 0A600h ; SPECIAL CODE 3655 00000FE7 E9B0010000 <1> jmp K57 ; BUFFER FILL 3656 <1> K37B: 3657 00000FEC B0F0 <1> mov al, 0F0h ; USE SPECIAL ASCII CODE 3658 00000FEE E9A9010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3659 <1> K35B: 3660 00000FF3 3C53 <1> cmp al, 83 ; TEST FOR DELETE KEY 3661 00000FF5 741F <1> je short K37C ; HANDLE WITH OTHER EDIT KEYS 3662 00000FF7 3C35 <1> cmp al, 53 ; TEST FOR KEYPAD / 3663 00000FF9 75AE <1> jne short K32A ; NOT THERE, NO OTHER E0 SPECIALS 3664 <1> ; 05/12/2021 3665 <1> ;jne K26 3666 00000FFB 66B800A4 <1> mov ax, 0A400h ; SPECIAL CODE 3667 00000FFF E998010000 <1> jmp K57 ; BUFFER FILL 3668 <1> K37: 3669 00001004 3C3B <1> cmp al, 59 ; TEST FOR FUNCTION KEYS (F1) 3670 00001006 72E4 <1> jb short K37B ; NO FN, HANDLE W/OTHER EXTENDED 3671 00001008 3C44 <1> cmp al, 68 ; IN KEYPAD REGION? 3672 0000100A 779D <1> ja short K32A ; IF SO, IGNORE 3673 <1> ; 11/06/2022 3674 <1> ;ja K26 3675 0000100C 80C42D <1> add ah, 45 ; CONVERT TO PSEUDO SCAN CODE 3676 <1> K37A: 3677 0000100F B000 <1> mov al, 0 ; ASCII CODE OF ZERO 3678 00001011 E986010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3679 <1> K37C: 3680 00001016 0450 <1> add al, 80 ; CONVERT SCAN CODE (EDIT KEYS) 3681 00001018 88C4 <1> mov ah, al ; (SCAN CODE NOT IN AH FOR INSERT) 3682 0000101A EBF3 <1> jmp short K37A ; PUT IT IN THE BUFFER 3683 <1> ; 3684 <1> ;----- NOT IN ALTERNATE SHIFT 3685 <1> K38: ; NOT-ALT-SHIFT 3686 <1> ; BL STILL HAS SHIFT FLAGS 3687 0000101C F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT? 3688 0000101F 7505 <1> jnz short K38A ; YES, START PROCESSING 3689 <1> ;jz K44 ; NOT-CTL-SHIFT 3690 <1> ; 05/12/2021 3691 00001021 E9AB000000 <1> jmp K44 3692 <1> ; 3693 <1> ;----- CONTROL SHIFT, TEST SPECIAL CHARACTERS 3694 <1> ;----- TEST FOR BREAK 3695 <1> K38A: 3696 00001026 3C46 <1> cmp al, SCROLL_KEY ; TEST FOR BREAK 3697 00001028 7530 <1> jne short K39 ; JUMP, NO-BREAK 3698 0000102A F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3699 0000102D 7405 <1> jz short K38B ; NO, BREAK IS VALID 3700 0000102F F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3701 00001032 7426 <1> jz short K39 ; NO-BREAK, TEST FOR PAUSE 3702 <1> K38B: 3703 00001034 8B1D[D0610000] <1> mov ebx, [BUFFER_HEAD] ; RESET BUFFER TO EMPTY 3704 0000103A 891D[D4610000] <1> mov [BUFFER_TAIL], ebx 3705 00001040 C605[C2610000]80 <1> mov byte [BIOS_BREAK], 80h ; TURN ON BIOS_BREAK BIT 3706 <1> ; 3707 <1> ;----- ENABLE KEYBOARD 3708 00001047 B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3709 00001049 E893010000 <1> call SHIP_IT ; EXECUTE ENABLE 3710 <1> ; 3711 <1> ; CTRL+BREAK code here !!! 3712 <1> ;INT 1BH ; BREAK INTERRUPT VECTOR 3713 <1> ; 17/10/2015 3714 0000104E E892190000 <1> call ctrlbrk ; control+break subroutine 3715 <1> ; 3716 <1> ;sub ax, ax ; PUT OUT DUMMY CHARACTER 3717 <1> ; 05/12/2021 3718 00001053 29C0 <1> sub eax, eax 3719 00001055 E942010000 <1> jmp K57 ; BUFFER_FILL 3720 <1> ; 3721 <1> ;----- TEST FOR PAUSE 3722 <1> K39: ; NO_BREAK 3723 0000105A F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3724 0000105D 7537 <1> jnz short K41 ; YES, THEN THIS CAN'T BE PAUSE 3725 0000105F 3C45 <1> cmp al, NUM_KEY ; LOOK FOR PAUSE KEY 3726 00001061 7533 <1> jne short K41 ; NO-PAUSE 3727 <1> K39P: 3728 00001063 800D[C4610000]08 <1> or byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG 3729 <1> ; 3730 <1> ;----- ENABLE KEYBOARD 3731 0000106A B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3732 0000106C E870010000 <1> call SHIP_IT ; EXECUTE ENABLE 3733 <1> K39A: 3734 00001071 B020 <1> mov al, EOI ; END OF INTERRUPT TO CONTROL PORT 3735 00001073 E620 <1> out 20h, al ;out INTA00, al ; ALLOW FURTHER KEYSTROKE INTERRUPTS 3736 <1> ; 3737 <1> ;----- DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON 3738 00001075 803D[C0610000]07 <1> cmp byte [CRT_MODE], 7 ; IS THIS BLACK AND WHITE CARD 3739 0000107C 740A <1> je short K40 ; YES, NOTHING TO DO 3740 0000107E 66BAD803 <1> mov dx, 03D8h ; PORT FOR COLOR CARD 3741 00001082 A0[C1610000] <1> mov al, [CRT_MODE_SET] ; GET THE VALUE OF THE CURRENT MODE 3742 00001087 EE <1> out dx, al ; SET THE CRT MODE, SO THAT CRT IS ON 3743 <1> ; 3744 <1> K40: ; PAUSE-LOOP 3745 00001088 F605[C4610000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG 3746 0000108F 75F7 <1> jnz short K40 ; LOOP UNTIL FLAG TURNED OFF 3747 <1> ; 3748 00001091 E98CFEFFFF <1> jmp K27 ; INTERRUPT_RETURN_NO_EOI 3749 <1> ; 3750 <1> ;----- TEST SPECIAL CASE KEY 55 3751 <1> K41: ; NO-PAUSE 3752 00001096 3C37 <1> cmp al, 55 ; TEST FOR */PRTSC KEY 3753 00001098 7513 <1> jne short K42 ; NOT-KEY-55 3754 0000109A F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3755 0000109D 7405 <1> jz short K41A ; NO, CTL-PRTSC IS VALID 3756 0000109F F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3757 000010A2 7421 <1> jz short K42B ; NO, TRANSLATE TO A FUNCTION 3758 <1> K41A: 3759 000010A4 66B80072 <1> mov ax, 114*256 ; START/STOP PRINTING SWITCH 3760 000010A8 E9EF000000 <1> jmp K57 ; BUFFER_FILL 3761 <1> ; 3762 <1> ;----- SET UP TO TRANSLATE CONTROL SHIFT 3763 <1> K42: ; NOT-KEY-55 3764 000010AD 3C0F <1> cmp al, 15 ; IS IT THE TAB KEY? 3765 000010AF 7414 <1> je short K42B ; YES, XLATE TO FUNCTION CODE 3766 000010B1 3C35 <1> cmp al, 53 ; IS IT THE / KEY? 3767 000010B3 750E <1> jne short K42A ; NO, NO MORE SPECIAL CASES 3768 000010B5 F6C702 <1> test bh, LC_E0 ; YES, IS IT FROM THE KEY PAD? 3769 000010B8 7409 <1> jz short K42A ; NO, JUST TRANSLATE 3770 000010BA 66B80095 <1> mov ax, 9500h ; YES, SPECIAL CODE FOR THIS ONE 3771 000010BE E9D9000000 <1> jmp K57 ; BUFFER FILL 3772 <1> K42A: 3773 <1> ;mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3774 000010C3 3C3B <1> cmp al, 59 ; IS IT IN CHARACTER TABLE? 3775 <1> ;jb short K45F ; YES, GO TRANSLATE CHAR 3776 <1> ;;jb K56 ; 20/02/2015 3777 <1> ;;jmp K64 ; 20/02/2015 3778 <1> K42B: 3779 000010C5 BB[B8600000] <1> mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3780 <1> ;;jmp K64 3781 <1> ;jb K56 ;; 20/02/2015 3782 <1> ; 05/12/2021 3783 000010CA 7267 <1> jb short K45F 3784 000010CC E9B9000000 <1> jmp K64 3785 <1> ; 3786 <1> ;----- NOT IN CONTROL SHIFT 3787 <1> K44: ; NOT-CTL-SHIFT 3788 000010D1 3C37 <1> cmp al, 55 ; PRINT SCREEN KEY? 3789 000010D3 7528 <1> jne short K45 ; NOT PRINT SCREEN 3790 000010D5 F6C710 <1> test bh, KBX ; IS THIS ENHANCED KEYBOARD? 3791 000010D8 7407 <1> jz short K44A ; NO, TEST FOR SHIFT STATE 3792 000010DA F6C702 <1> test bh, LC_E0 ; YES, LAST CODE A MARKER? 3793 000010DD 7507 <1> jnz short K44B ; YES, IS PRINT SCREEN 3794 000010DF EB41 <1> jmp short K45C ; NO, TRANSLATE TO '*' CHARACTER 3795 <1> K44A: 3796 000010E1 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN? 3797 000010E4 743C <1> jz short K45C ; NO, TRANSLATE TO '*' CHARACTER 3798 <1> ; 3799 <1> ;----- ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION 3800 <1> K44B: 3801 000010E6 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3802 000010E8 E8F4000000 <1> call SHIP_IT ; EXECUTE ENABLE 3803 000010ED B020 <1> mov al, EOI ; END OF CURRENT INTERRUPT 3804 000010EF E620 <1> out 20h, al ;out INTA00, al ; SO FURTHER THINGS CAN HAPPEN 3805 <1> ; Print Screen !!! ; ISSUE PRINT SCREEN INTERRUPT (INT 05h) 3806 <1> ;PUSH BP ; SAVE POINTER 3807 <1> ;INT 5H ; ISSUE PRINT SCREEN INTERRUPT 3808 <1> ;POP BP ; RESTORE POINTER 3809 000010F1 8025[C6610000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS 3810 000010F8 E925FEFFFF <1> jmp K27 ; GO BACK WITHOUT EOI OCCURRING 3811 <1> ; 3812 <1> ;----- HANDLE IN-CORE KEYS 3813 <1> K45: ; NOT-PRINT-SCREEN 3814 000010FD 3C3A <1> cmp al, 58 ; TEST FOR IN-CORE AREA 3815 000010FF 7734 <1> ja short K46 ; JUMP IF NOT 3816 00001101 3C35 <1> cmp al, 53 ; IS THIS THE '/' KEY? 3817 00001103 7505 <1> jne short K45A ; NO, JUMP 3818 00001105 F6C702 <1> test bh, LC_E0 ; WAS THE LAST CODE THE MARKER? 3819 00001108 7518 <1> jnz short K45C ; YES, TRANSLATE TO CHARACTER 3820 <1> K45A: 3821 0000110A B91A000000 <1> mov ecx, 26 ; LENGHT OF SEARCH 3822 0000110F BF[8E600000] <1> mov edi, K30+10 ; POINT TO TABLE OF A-Z CHARS 3823 00001114 F2AE <1> repne scasb ; IS THIS A LETTER KEY? 3824 <1> ; 20/02/2015 3825 00001116 7505 <1> jne short K45B ; NO, SYMBOL KEY 3826 <1> ; 3827 00001118 F6C340 <1> test bl, CAPS_STATE ; ARE WE IN CAPS_LOCK? 3828 0000111B 750C <1> jnz short K45D ; TEST FOR SURE 3829 <1> K45B: 3830 0000111D F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3831 00001120 750C <1> jnz short K45E ; YES, UPPERCASE 3832 <1> ; NO, LOWERCASE 3833 <1> K45C: 3834 00001122 BB[10610000] <1> mov ebx, K10 ; TRANSLATE TO LOWERCASE LETTERS 3835 00001127 EB51 <1> jmp short K56 3836 <1> K45D: ; ALMOST-CAPS-STATE 3837 00001129 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO? 3838 0000112C 75F4 <1> jnz short K45C ; SHIFTED TEMP OUT OF CAPS STATE 3839 <1> K45E: 3840 0000112E BB[68610000] <1> mov ebx, K11 ; TRANSLATE TO UPPER CASE LETTERS 3841 00001133 EB45 <1> K45F: jmp short K56 3842 <1> ; 3843 <1> ;----- TEST FOR KEYS F1 - F10 3844 <1> K46: ; NOT IN-CORE AREA 3845 00001135 3C44 <1> cmp al, 68 ; TEST FOR F1 - F10 3846 <1> ;ja short K47 ; JUMP IF NOT 3847 <1> ;jmp short K53 ; YES, GO DO FN KEY PROCESS 3848 00001137 7635 <1> jna short K53 3849 <1> ; 3850 <1> ;----- HANDLE THE NUMERIC PAD KEYS 3851 <1> K47: ; NOT F1 - F10 3852 00001139 3C53 <1> cmp al, 83 ; TEST NUMPAD KEYS 3853 0000113B 772D <1> ja short K52 ; JUMP IF NOT 3854 <1> ; 3855 <1> ;----- KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION 3856 <1> K48: 3857 0000113D 3C4A <1> cmp al, 74 ; SPECIAL CASE FOR MINUS 3858 0000113F 74ED <1> je short K45E ; GO TRANSLATE 3859 00001141 3C4E <1> cmp al, 78 ; SPECIAL CASE FOR PLUS 3860 00001143 74E9 <1> je short K45E ; GO TRANSLATE 3861 00001145 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OFTHE NEW KEYS? 3862 00001148 750A <1> jnz short K49 ; YES, TRANSLATE TO BASE STATE 3863 <1> ; 3864 0000114A F6C320 <1> test bl, NUM_STATE ; ARE WE IN NUM LOCK 3865 0000114D 7514 <1> jnz short K50 ; TEST FOR SURE 3866 0000114F F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3867 <1> ;jnz short K51 ; IF SHIFTED, REALLY NUM STATE 3868 00001152 75DA <1> jnz short K45E 3869 <1> ; 3870 <1> ;----- BASE CASE FOR KEYPAD 3871 <1> K49: 3872 00001154 3C4C <1> cmp al, 76 ; SPECIAL CASE FOR BASE STATE 5 3873 00001156 7504 <1> jne short K49A ; CONTINUE IF NOT KEYPAD 5 3874 00001158 B0F0 <1> mov al, 0F0h ; SPECIAL ASCII CODE 3875 0000115A EB40 <1> jmp short K57 ; BUFFER FILL 3876 <1> K49A: 3877 0000115C BB[10610000] <1> mov ebx, K10 ; BASE CASE TABLE 3878 00001161 EB27 <1> jmp short K64 ; CONVERT TO PSEUDO SCAN 3879 <1> ; 3880 <1> ;----- MIGHT BE NUM LOCK, TEST SHIFT STATUS 3881 <1> K50: ; ALMOST-NUM-STATE 3882 00001163 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 3883 00001166 75EC <1> jnz short K49 ; SHIFTED TEMP OUT OF NUM STATE 3884 00001168 EBC4 <1> K51: jmp short K45E ; REALLY NUM STATE 3885 <1> ; 3886 <1> ;----- TEST FOR THE NEW KEYS ON WT KEYBOARDS 3887 <1> K52: ; NOT A NUMPAD KEY 3888 0000116A 3C56 <1> cmp al, 86 ; IS IT THE NEW WT KEY? 3889 <1> ;jne short K53 ; JUMP IF NOT 3890 <1> ;jmp short K45B ; HANDLE WITH REST OF LETTER KEYS 3891 0000116C 74AF <1> je short K45B 3892 <1> ; 3893 <1> ;----- MUST BE F11 OR F12 3894 <1> K53: ; F1 - F10 COME HERE, TOO 3895 0000116E F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE 3896 00001171 74E1 <1> jz short K49 ; JUMP, LOWER CASE PSEUDO SC'S 3897 <1> ; 20/02/2015 3898 00001173 BB[68610000] <1> mov ebx, K11 ; UPPER CASE PSEUDO SCAN CODES 3899 00001178 EB10 <1> jmp short K64 ; TRANSLATE SCAN 3900 <1> ; 3901 <1> ;----- TRANSLATE THE CHARACTER 3902 <1> K56: ; TRANSLATE-CHAR 3903 0000117A FEC8 <1> dec al ; CONVERT ORIGIN 3904 0000117C D7 <1> xlat ; CONVERT THE SCAN CODE TO ASCII 3905 0000117D F605[C6610000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3906 00001184 7416 <1> jz short K57 ; NO, GO FILL BUFFER 3907 00001186 B4E0 <1> mov ah, MC_E0 ; YES, PUT SPECIAL MARKER IN AH 3908 00001188 EB12 <1> jmp short K57 ; PUT IT INTO THE BUFFER 3909 <1> ; 3910 <1> ;----- TRANSLATE SCAN FOR PSEUDO SCAN CODES 3911 <1> K64: ; TRANSLATE-SCAN-ORGD 3912 0000118A FEC8 <1> dec al ; CONVERT ORIGIN 3913 0000118C D7 <1> xlat ; CTL TABLE SCAN 3914 0000118D 88C4 <1> mov ah, al ; PUT VALUE INTO AH 3915 0000118F B000 <1> mov al, 0 ; ZERO ASCII CODE 3916 00001191 F605[C6610000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3917 00001198 7402 <1> jz short K57 ; NO, GO FILL BUFFER 3918 0000119A B0E0 <1> mov al, MC_E0 ; YES, PUT SPECIAL MARKER IN AL 3919 <1> ; 3920 <1> ;----- PUT CHARACTER INTO BUFFER 3921 <1> K57: ; BUFFER_FILL 3922 0000119C 3CFF <1> cmp al, -1 ; IS THIS AN IGNORE CHAR 3923 0000119E 7405 <1> je short K59 ; YES, DO NOTHING WITH IT 3924 <1> ; 05/12/2021 3925 <1> ;je K26 ; YES, DO NOTHING WITH IT 3926 000011A0 80FCFF <1> cmp ah, -1 ; LOOK FOR -1 PSEUDO SCAN 3927 <1> ; 05/12/2021 3928 000011A3 7505 <1> jne short K61 ; NEAR_INTERRUPT_RETURN 3929 <1> ;je K26 ; INTERRUPT_RETURN 3930 <1> K59: ; NEAR_INTERRUPT_RETURN 3931 000011A5 E96CFDFFFF <1> jmp K26 ; INTERRUPT_RETURN 3932 <1> K61: ; NOT-CAPS-STATE 3933 000011AA 8B1D[D4610000] <1> mov ebx, [BUFFER_TAIL] ; GET THE END POINTER TO THE BUFFER 3934 000011B0 89DE <1> mov esi, ebx ; SAVE THE VALUE 3935 000011B2 E8AEFAFFFF <1> call _K4 ; ADVANCE THE TAIL 3936 000011B7 3B1D[D0610000] <1> cmp ebx, [BUFFER_HEAD] ; HAS THE BUFFER WRAPPED AROUND 3937 000011BD 740E <1> je short K62 ; BUFFER_FULL_BEEP 3938 000011BF 668906 <1> mov [esi], ax ; STORE THE VALUE 3939 000011C2 891D[D4610000] <1> mov [BUFFER_TAIL], ebx ; MOVE THE POINTER UP 3940 000011C8 E949FDFFFF <1> jmp K26 3941 <1> ;;cli ; TURN OFF INTERRUPTS 3942 <1> ;;mov al, EOI ; END OF INTERRUPT COMMAND 3943 <1> ;;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3944 <1> ;mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3945 <1> ;call SHIP_IT ; EXECUTE ENABLE 3946 <1> ;mov ax, 9102h ; MOVE IN POST CODE & TYPE 3947 <1> ;int 15h ; PERFORM OTHER FUNCTION 3948 <1> ;;and byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 3949 <1> ;jmp K27A ; INTERRUPT_RETURN 3950 <1> ;;jmp K27 3951 <1> ; 3952 <1> ;----- BUFFER IS FULL SOUND THE BEEPER 3953 <1> K62: 3954 000011CD B020 <1> mov al, EOI ; ENABLE INTERRUPT CONTROLLER CHIP 3955 000011CF E620 <1> out INTA00, al 3956 000011D1 66B9A602 <1> mov cx, 678 ; DIVISOR FOR 1760 HZ 3957 000011D5 B304 <1> mov bl, 4 ; SHORT BEEP COUNT (1/16 + 1/64 DELAY) 3958 000011D7 E883010000 <1> call beep ; GO TO COMMON BEEP HANDLER 3959 000011DC E941FDFFFF <1> jmp K27 ; EXIT 3960 <1> 3961 <1> SHIP_IT: 3962 <1> ;--------------------------------------------------------------------------------- 3963 <1> ; SHIP_IT 3964 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3965 <1> ; TO THE KEYBOARD CONTROLLER. 3966 <1> ;--------------------------------------------------------------------------------- 3967 <1> ; 3968 <1> ;push ax ; SAVE DATA TO SEND 3969 <1> ; 05/12/2021 3970 000011E1 50 <1> push eax 3971 <1> ;----- WAIT FOR COMMAND TO ACCEPTED 3972 000011E2 FA <1> cli ; DISABLE INTERRUPTS TILL DATA SENT 3973 <1> ; xor ecx, ecx ; CLEAR TIMEOUT COUNTER 3974 000011E3 B900000100 <1> mov ecx, 10000h 3975 <1> S10: 3976 000011E8 E464 <1> in al, STATUS_PORT ; READ KEYBOARD CONTROLLER STATUS 3977 000011EA A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ITS INPUT BUFFER BUSY 3978 000011EC E0FA <1> loopnz S10 ; WAIT FOR COMMAND TO BE ACCEPTED 3979 <1> 3980 <1> ;pop ax ; GET DATA TO SEND 3981 <1> ; 05/12/2021 3982 000011EE 58 <1> pop eax 3983 000011EF E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROLLER 3984 000011F1 FB <1> sti ; ENABLE INTERRUPTS AGAIN 3985 000011F2 C3 <1> retn ; RETURN TO CALLER 3986 <1> 3987 <1> SND_DATA: 3988 <1> ; --------------------------------------------------------------------------------- 3989 <1> ; SND_DATA 3990 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3991 <1> ; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO 3992 <1> ; HANDLES ANY RETRIES IF REQUIRED 3993 <1> ; --------------------------------------------------------------------------------- 3994 <1> ; 3995 <1> ;push ax ; SAVE REGISTERS 3996 <1> ;push bx 3997 <1> ; 05/12/2021 3998 000011F3 50 <1> push eax 3999 000011F4 53 <1> push ebx 4000 000011F5 51 <1> push ecx 4001 000011F6 88C7 <1> mov bh, al ; SAVE TRANSMITTED BYTE FOR RETRIES 4002 000011F8 B303 <1> mov bl, 3 ; LOAD RETRY COUNT 4003 <1> SD0: 4004 000011FA FA <1> cli ; DISABLE INTERRUPTS 4005 000011FB 8025[C5610000]CF <1> and byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS 4006 <1> ; 4007 <1> ;----- WAIT FOR COMMAND TO BE ACCEPTED 4008 00001202 B900000100 <1> mov ecx, 10000h ; MAXIMUM WAIT COUNT 4009 <1> SD5: 4010 00001207 E464 <1> in al, STATUS_PORT ; READ KEYBOARD PROCESSOR STATUS PORT 4011 00001209 A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ANY PENDING COMMAND 4012 0000120B E0FA <1> loopnz SD5 ; WAIT FOR COMMAND TO BE ACCEPTED 4013 <1> ; 4014 0000120D 88F8 <1> mov al, bh ; REESTABLISH BYTE TO TRANSMIT 4015 0000120F E660 <1> out PORT_A, al ; SEND BYTE 4016 00001211 FB <1> sti ; ENABLE INTERRUPTS 4017 <1> ;mov cx, 01A00h ; LOAD COUNT FOR 10 ms+ 4018 00001212 B9FFFF0000 <1> mov ecx, 0FFFFh 4019 <1> SD1: 4020 00001217 F605[C5610000]30 <1> test byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET 4021 0000121E 750F <1> jnz short SD3 ; IF SET, SOMETHING RECEIVED GO PROCESS 4022 00001220 E2F5 <1> loop SD1 ; OTHERWISE WAIT 4023 <1> SD2: 4024 00001222 FECB <1> dec bl ; DECREMENT RETRY COUNT 4025 00001224 75D4 <1> jnz short SD0 ; RETRY TRANSMISSION 4026 00001226 800D[C5610000]80 <1> or byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG 4027 0000122D EB09 <1> jmp short SD4 ; RETRIES EXHAUSTED FORGET TRANSMISSION 4028 <1> SD3: 4029 0000122F F605[C5610000]10 <1> test byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE 4030 00001236 74EA <1> jz short SD2 ; IF NOT, GO RESEND 4031 <1> SD4: 4032 00001238 59 <1> pop ecx ; RESTORE REGISTERS 4033 <1> ;pop bx 4034 <1> ;pop ax 4035 <1> ; 05/12/2021 4036 00001239 5B <1> pop ebx 4037 0000123A 58 <1> pop eax 4038 0000123B C3 <1> retn ; RETURN, GOOD TRANSMISSION 4039 <1> 4040 <1> SND_LED: 4041 <1> ; --------------------------------------------------------------------------------- 4042 <1> ; SND_LED 4043 <1> ; THIS ROUTINES TURNS ON THE MODE INDICATORS. 4044 <1> ; 4045 <1> ;---------------------------------------------------------------------------------- 4046 <1> ; 4047 0000123C FA <1> cli ; TURN OFF INTERRUPTS 4048 0000123D F605[C5610000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 4049 00001244 755F <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 4050 <1> ; 4051 00001246 800D[C5610000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 4052 0000124D B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 4053 0000124F E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 4054 00001251 EB11 <1> jmp short SL0 ; GO SEND MODE INDICATOR COMMAND 4055 <1> SND_LED1: 4056 00001253 FA <1> cli ; TURN OFF INTERRUPTS 4057 00001254 F605[C5610000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 4058 0000125B 7548 <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 4059 <1> ; 4060 0000125D 800D[C5610000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 4061 <1> SL0: 4062 00001264 B0ED <1> mov al, LED_CMD ; LED CMD BYTE 4063 00001266 E888FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 4064 0000126B FA <1> cli 4065 0000126C E836000000 <1> call MAKE_LED ; GO FORM INDICATOR DATA BYTE 4066 00001271 8025[C5610000]F8 <1> and byte [KB_FLAG_2], 0F8h ; ~KB_LEDS ; CLEAR MODE INDICATOR BITS 4067 00001278 0805[C5610000] <1> or [KB_FLAG_2], al ; SAVE PRESENT INDICATORS FOR NEXT TIME 4068 0000127E F605[C5610000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 4069 00001285 750F <1> jnz short SL2 ; IF SO, BYPASS SECOND BYTE TRANSMISSION 4070 <1> ; 4071 00001287 E867FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 4072 0000128C FA <1> cli ; TURN OFF INTERRUPTS 4073 0000128D F605[C5610000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 4074 00001294 7408 <1> jz short SL3 ; IF NOT, DON'T SEND AN ENABLE COMMAND 4075 <1> SL2: 4076 00001296 B0F4 <1> mov al, KB_ENABLE ; GET KEYBOARD CSA ENABLE COMMAND 4077 00001298 E856FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 4078 0000129D FA <1> cli ; TURN OFF INTERRUPTS 4079 <1> SL3: 4080 0000129E 8025[C5610000]3F <1> and byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR 4081 <1> SL1: ; UPDATE AND TRANSMIT ERROR FLAG 4082 000012A5 FB <1> sti ; ENABLE INTERRUPTS 4083 000012A6 C3 <1> retn ; RETURN TO CALLER 4084 <1> 4085 <1> MAKE_LED: 4086 <1> ;--------------------------------------------------------------------------------- 4087 <1> ; MAKE_LED 4088 <1> ; THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF 4089 <1> ; THE MODE INDICATORS. 4090 <1> ;--------------------------------------------------------------------------------- 4091 <1> ; 4092 <1> ;push cx ; SAVE CX 4093 000012A7 A0[C3610000] <1> mov al, [KB_FLAG] ; GET CAPS & NUM LOCK INDICATORS 4094 000012AC 2470 <1> and al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS 4095 <1> ;mov cl, 4 ; SHIFT COUNT 4096 <1> ;rol al, cl ; SHIFT BITS OVER TO TURN ON INDICATORS 4097 000012AE C0C004 <1> rol al, 4 ; 20/02/2015 4098 000012B1 2407 <1> and al, 07h ; MAKE SURE ONLY MODE BITS ON 4099 <1> ;pop cx 4100 000012B3 C3 <1> retn ; RETURN TO CALLER 4101 <1> 4102 <1> ; % include 'kybdata.inc' ; KEYBOARD DATA ; 11/03/2015 4103 <1> 4104 <1> ; /// End Of KEYBOARD FUNCTIONS /// 4105 4106 %include 'video.s' ; 07/03/2015 4107 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 4108 <1> ; (re-write kernel for test by using previous version without a major defect) 4109 <1> ; **************************************************************************** 4110 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - VIDEO.INC 4111 <1> ; Last Modification: 14/06/2022 4112 <1> ; (Video Data is in 'VIDATA.INC') 4113 <1> ; 4114 <1> ; ///////// VIDEO (CGA) FUNCTIONS /////////////// 4115 <1> 4116 <1> ; 27/02/2022 4117 <1> ; 23/02/2022 4118 <1> ; 21/02/2022 (Retro UNIX 386 v1.2) 4119 <1> ; 07/02/2022 (Retro UNIX 386 V1&v1.1) 4120 <1> ; 02/02/2022 (simplified scroll up) 4121 <1> ; 16/01/2016 4122 <1> ; 30/06/2015 4123 <1> ; 27/06/2015 4124 <1> ; 11/03/2015 4125 <1> ; 02/09/2014 4126 <1> ; 30/08/2014 4127 <1> ; VIDEO FUNCTIONS 4128 <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014) 4129 <1> 4130 <1> write_tty: 4131 <1> ; 02/02/2022 4132 <1> ; 13/08/2015 4133 <1> ; 02/09/2014 4134 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 4135 <1> ; 01/02/2014 (Retro UNIX 8086 v1 - last update) 4136 <1> ; 03/12/2013 (Retro UNIX 8086 v1 - beginning) 4137 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 4138 <1> ; 4139 <1> ; INPUT -> AH = Color (Forecolor, Backcolor) 4140 <1> ; AL = Character to be written 4141 <1> ; EBX = Video Page (0 to 7) 4142 <1> ; (BH = 0 --> Video Mode 3) 4143 <1> 4144 <1> RVRT equ 00001000b ; VIDEO VERTICAL RETRACE BIT 4145 <1> RHRZ equ 00000001b ; VIDEO HORIZONTAL RETRACE BIT 4146 <1> 4147 <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code 4148 <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO 4149 <1> ; 4150 <1> ; 06/10/85 VIDEO DISPLAY BIOS 4151 <1> ; 4152 <1> ;--- WRITE_TTY ------------------------------------------------------------------ 4153 <1> ; : 4154 <1> ; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE : 4155 <1> ; VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT : 4156 <1> ; CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION. : 4157 <1> ; IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN : 4158 <1> ; IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW : 4159 <1> ; ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW, : 4160 <1> ; FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE. : 4161 <1> ; WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE : 4162 <1> ; NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS : 4163 <1> ; LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE, : 4164 <1> ; THE 0 COLOR IS USED. : 4165 <1> ; ENTRY -- : 4166 <1> ; (AH) = CURRENT CRT MODE : 4167 <1> ; (AL) = CHARACTER TO BE WRITTEN : 4168 <1> ; NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE : 4169 <1> ; HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS : 4170 <1> ; (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE : 4171 <1> ; EXIT -- : 4172 <1> ; ALL REGISTERS SAVED : 4173 <1> ;-------------------------------------------------------------------------------- 4174 <1> 4175 000012B4 FA <1> cli 4176 <1> ; 4177 <1> ; READ CURSOR (04/12/2013) 4178 <1> ; Retro UNIX 386 v1 Modifications: 30/08/2014 4179 000012B5 08FF <1> or bh, bh 4180 <1> ;jnz beeper 4181 <1> ; 02/02/2022 4182 000012B7 7405 <1> jz short u14 4183 000012B9 E992000000 <1> jmp beeper 4184 <1> u14: 4185 <1> ; 02/02/2022 4186 <1> ;; 01/09/2014 4187 <1> ;cmp byte [CRT_MODE], 3 4188 <1> ;je short m3 4189 <1> ;; 4190 <1> ;call set_mode 4191 <1> m3: 4192 000012BE 89DE <1> mov esi, ebx ; 13/08/2015 (0 to 7) 4193 <1> ;shl si, 1 4194 <1> ; 02/02/2022 4195 000012C0 D1E6 <1> shl esi, 1 4196 000012C2 81C6[86670000] <1> add esi, cursor_posn 4197 000012C8 668B16 <1> mov dx, [esi] 4198 <1> ; 4199 <1> ; dx now has the current cursor position 4200 <1> ; 4201 000012CB 3C0D <1> cmp al, 0Dh ; is it carriage return or control character 4202 000012CD 7647 <1> jbe short u8 4203 <1> ; 4204 <1> ; write the char to the screen 4205 <1> u0: 4206 <1> ; ah = attribute/color 4207 <1> ; al = character 4208 <1> ; bl = video page number (0 to 7) 4209 <1> ; bh = 0 4210 <1> ; 4211 000012CF E8D2010000 <1> call write_c_current 4212 <1> ; 4213 <1> ; position the cursor for next char 4214 000012D4 FEC2 <1> inc dl ; next column 4215 <1> ;cmp dl, [CRT_COLS] 4216 000012D6 80FA50 <1> cmp dl, 80 ; test for column overflow 4217 <1> ;jne set_cpos 4218 <1> ; 02/02/2022 4219 000012D9 7405 <1> je short u13 4220 000012DB E9DE000000 <1> jmp set_cpos 4221 <1> u13: 4222 000012E0 B200 <1> mov dl, 0 ; column = 0 4223 <1> u10: ; (line feed found) 4224 000012E2 80FE18 <1> cmp dh, 25-1 ; check for last row 4225 000012E5 7228 <1> jb short u6 4226 <1> ; 4227 <1> ; scroll required 4228 <1> u1: 4229 <1> ; SET CURSOR POSITION (04/12/2013) 4230 000012E7 E8D2000000 <1> call set_cpos 4231 <1> ; 4232 <1> ; determine value to fill with during scroll 4233 <1> u2: 4234 <1> ; READ_AC_CURRENT : 4235 <1> ; THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER 4236 <1> ; AT THE CURRENT CURSOR POSITION 4237 <1> ; 4238 <1> ; INPUT 4239 <1> ; (AH) = CURRENT CRT MODE 4240 <1> ; (BH) = DISPLAY PAGE ( ALPHA MODES ONLY ) 4241 <1> ; (DS) = DATA SEGMENT 4242 <1> ; (ES) = REGEN SEGMENT 4243 <1> ; OUTPUT 4244 <1> ; (AL) = CHARACTER READ 4245 <1> ; (AH) = ATTRIBUTE READ 4246 <1> ; 4247 <1> ; mov ah, [CRT_MODE] ; move current mode into ah 4248 <1> ; 4249 <1> ; bl = video page number 4250 <1> ; 4251 000012EC E829010000 <1> call find_position ; get regen location and port address 4252 <1> ; dx = status port 4253 <1> ; esi = cursor location/address 4254 <1> p11: 4255 000012F1 FB <1> sti ; enable interrupts 4256 000012F2 90 <1> nop ; allow for small interupts window 4257 000012F3 FA <1> cli ; blocks interrupts for single loop 4258 000012F4 EC <1> in al, dx ; get status from adapter 4259 000012F5 A801 <1> test al, RHRZ ; is horizontal retrace low 4260 000012F7 75F8 <1> jnz short p11 ; wait until it is 4261 <1> p12: ; now wait for either retrace high 4262 000012F9 EC <1> in al, dx ; get status 4263 000012FA A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 4264 000012FC 74FB <1> jz short p12 ; wait until either is active 4265 <1> p13: 4266 000012FE 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 4267 00001304 668B06 <1> mov ax, [esi] ; get the character and attribute 4268 <1> ; 4269 <1> ; al = character, ah = attribute 4270 <1> ; 4271 00001307 FB <1> sti 4272 <1> ; bl = video page number 4273 <1> u3: 4274 <1> ;;mov ax, 0601h ; scroll one line 4275 <1> ;;sub cx, cx ; upper left corner 4276 <1> ;;mov dh, 25-1 ; lower right row 4277 <1> ;;;mov dl, [CRT_COLS] 4278 <1> ;mov dl, 80 ; lower right column 4279 <1> ;;dec dl 4280 <1> ;;mov dl, 79 4281 <1> 4282 <1> ;;call scroll_up ; 04/12/2013 4283 <1> ;;; 11/03/2015 4284 <1> ; 02/09/2014 4285 <1> ;;;mov cx, [crt_ulc] ; Upper left corner (0000h) 4286 <1> ;;;mov dx, [crt_lrc] ; Lower right corner (184Fh) 4287 <1> ; 11/03/2015 4288 <1> ;sub cx, cx 4289 <1> ;mov dx, 184Fh ; dl= 79 (column), dh = 24 (row) 4290 <1> ; 4291 <1> ; 02/02/2022 (simplied scroll up) 4292 <1> ; ((retro unix 8086 v1 'scroll_up' in 'u9.s')) 4293 <1> ; 4294 00001308 B001 <1> mov al, 1 ; scroll 1 line up 4295 <1> ; ah = attribute 4296 0000130A E935010000 <1> jmp scroll_up 4297 <1> ;u4: 4298 <1> ;;int 10h ; video-call return 4299 <1> ; scroll up the screen 4300 <1> ; tty return 4301 <1> ;u5: 4302 <1> ;retn ; return to the caller 4303 <1> 4304 <1> u6: ; set-cursor-inc 4305 0000130F FEC6 <1> inc dh ; next row 4306 <1> ; set cursor 4307 <1> ;u7: 4308 <1> ;;mov ah, 02h 4309 <1> ;;jmp short u4 ; establish the new cursor 4310 <1> ;call set_cpos 4311 <1> ;jmp short u5 4312 00001311 E9A8000000 <1> jmp set_cpos 4313 <1> 4314 <1> ; check for control characters 4315 <1> u8: 4316 00001316 7434 <1> je short u9 4317 00001318 3C0A <1> cmp al, 0Ah ; is it a line feed (0Ah) 4318 0000131A 74C6 <1> je short u10 4319 0000131C 3C07 <1> cmp al, 07h ; is it a bell 4320 0000131E 7430 <1> je short u11 4321 00001320 3C08 <1> cmp al, 08h ; is it a backspace 4322 <1> ;jne short u0 4323 00001322 7420 <1> je short bs ; 12/12/2013 4324 <1> ; 12/12/2013 (tab stop) 4325 00001324 3C09 <1> cmp al, 09h ; is it a tab stop 4326 00001326 75A7 <1> jne short u0 4327 00001328 88D0 <1> mov al, dl 4328 0000132A 6698 <1> cbw 4329 0000132C B108 <1> mov cl, 8 4330 0000132E F6F1 <1> div cl 4331 00001330 28E1 <1> sub cl, ah 4332 <1> ts: 4333 <1> ; 02/09/2014 4334 <1> ; 01/09/2014 4335 00001332 B020 <1> mov al, 20h 4336 <1> tsloop: 4337 <1> ;push cx 4338 <1> ;push ax 4339 <1> ; 02/02/2022 4340 00001334 51 <1> push ecx 4341 00001335 50 <1> push eax 4342 00001336 30FF <1> xor bh, bh 4343 <1> ;mov bl, [active_page] 4344 00001338 E881FFFFFF <1> call m3 4345 <1> ; 02/02/2022 4346 0000133D 58 <1> pop eax 4347 0000133E 59 <1> pop ecx 4348 <1> ;pop ax ; ah = attribute/color 4349 <1> ;pop cx 4350 0000133F FEC9 <1> dec cl 4351 00001341 75F1 <1> jnz short tsloop 4352 00001343 C3 <1> retn 4353 <1> bs: 4354 <1> ; back space found 4355 00001344 08D2 <1> or dl, dl ; is it already at start of line 4356 <1> ;je short u7 ; set_cursor 4357 00001346 7476 <1> jz short set_cpos 4358 <1> ;dec dx ; no -- just move it back 4359 <1> ; 02/02/2022 4360 00001348 FECA <1> dec dl 4361 <1> ;jmp short u7 4362 0000134A EB72 <1> jmp short set_cpos 4363 <1> 4364 <1> ; carriage return found 4365 <1> u9: 4366 0000134C B200 <1> mov dl, 0 ; move to first column 4367 <1> ;jmp short u7 4368 0000134E EB6E <1> jmp short set_cpos 4369 <1> 4370 <1> ; line feed found 4371 <1> ;u10: 4372 <1> ; cmp dh, 25-1 ; bottom of screen 4373 <1> ; jne short u6 ; no, just set the cursor 4374 <1> ; jmp u1 ; yes, scroll the screen 4375 <1> 4376 <1> beeper: 4377 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4378 <1> ; 18/01/2014 4379 <1> ; 03/12/2013 4380 <1> ; bell found 4381 <1> u11: 4382 00001350 FB <1> sti 4383 00001351 3A1D[96670000] <1> cmp bl, [active_page] 4384 00001357 7551 <1> jne short u12 ; Do not sound the beep 4385 <1> ; if it is not written on the active page 4386 00001359 66B93305 <1> mov cx, 1331 ; divisor for 896 hz tone 4387 0000135D B31F <1> mov bl, 31 ; set count for 31/64 second for beep 4388 <1> ;call beep ; sound the pod bell 4389 <1> ;jmp short u5 ; tty_return 4390 <1> ;retn 4391 <1> 4392 <1> TIMER equ 040h ; 8254 TIMER - BASE ADDRESS 4393 <1> PORT_B equ 061h ; PORT B READ/WRITE DIAGNOSTIC REGISTER 4394 <1> GATE2 equ 00000001b ; TIMER 2 INPUT CATE CLOCK BIT 4395 <1> SPK2 equ 00000010b ; SPEAKER OUTPUT DATA ENABLE BIT 4396 <1> 4397 <1> beep: 4398 <1> ; 07/02/2015 4399 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4400 <1> ; 18/01/2014 4401 <1> ; 03/12/2013 4402 <1> ; 4403 <1> ; TEST4.ASM - 06/10/85 POST AND BIOS UTILITY ROUTINES 4404 <1> ; 4405 <1> ; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE 4406 <1> ; 4407 <1> ; ENTRY: 4408 <1> ; (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND ) 4409 <1> ; (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ) 4410 <1> ; EXIT: : 4411 <1> ; (AX),(BL),(CX) MODIFIED. 4412 <1> 4413 0000135F 9C <1> pushf ; 18/01/2014 ; save interrupt status 4414 00001360 FA <1> cli ; block interrupts during update 4415 00001361 B0B6 <1> mov al, 10110110b ; select timer 2, lsb, msb binary 4416 00001363 E643 <1> out TIMER+3, al ; write timer mode register 4417 00001365 EB00 <1> jmp $+2 ; I/O delay 4418 00001367 88C8 <1> mov al, cl ; divisor for hz (low) 4419 00001369 E642 <1> out TIMER+2,AL ; write timer 2 count - lsb 4420 0000136B EB00 <1> jmp $+2 ; I/O delay 4421 0000136D 88E8 <1> mov al, ch ; divisor for hz (high) 4422 0000136F E642 <1> out TIMER+2, al ; write timer 2 count - msb 4423 00001371 E461 <1> in al, PORT_B ; get current setting of port 4424 00001373 88C4 <1> mov ah, al ; save that setting 4425 00001375 0C03 <1> or al, GATE2+SPK2 ; gate timer 2 and turn speaker on 4426 00001377 E661 <1> out PORT_B, al ; and restore interrupt status 4427 <1> ;popf ; 18/01/2014 4428 00001379 FB <1> sti 4429 <1> g7: ; 1/64 second per count (bl) 4430 0000137A B90B040000 <1> mov ecx, 1035 ; delay count for 1/64 of a second 4431 0000137F E827000000 <1> call waitf ; go to beep delay 1/64 count 4432 00001384 FECB <1> dec bl ; (bl) length count expired? 4433 00001386 75F2 <1> jnz short g7 ; no - continue beeping speaker 4434 <1> ; 4435 <1> ;pushf ; save interrupt status 4436 00001388 FA <1> cli ; 18/01/2014 ; block interrupts during update 4437 00001389 E461 <1> in al, PORT_B ; get current port value 4438 <1> ;or al, not (GATE2+SPK2) ; isolate current speaker bits in case 4439 0000138B 0CFC <1> or al, ~(GATE2+SPK2) 4440 0000138D 20C4 <1> and ah, al ; someone turned them off during beep 4441 0000138F 88E0 <1> mov al, ah ; recover value of port 4442 <1> ;or al, not (GATE2+SPK2) ; force speaker data off 4443 00001391 0CFC <1> or al, ~(GATE2+SPK2) ; isolate current speaker bits in case 4444 00001393 E661 <1> out PORT_B, al ; and stop speaker timer 4445 <1> ;popf ; restore interrupt flag state 4446 00001395 FB <1> sti 4447 00001396 B90B040000 <1> mov ecx, 1035 ; force 1/64 second delay (short) 4448 0000139B E80B000000 <1> call waitf ; minimum delay between all beeps 4449 <1> ;pushf ; save interrupt status 4450 000013A0 FA <1> cli ; block interrupts during update 4451 000013A1 E461 <1> in al, PORT_B ; get current port value in case 4452 000013A3 2403 <1> and al, GATE2+SPK2 ; someone turned them on 4453 000013A5 08E0 <1> or al, ah ; recover value of port_b 4454 000013A7 E661 <1> out PORT_B, al ; restore speaker status 4455 000013A9 9D <1> popf ; restore interrupt flag state 4456 <1> u12: 4457 000013AA C3 <1> retn 4458 <1> 4459 <1> REFRESH_BIT equ 00010000b ; REFRESH TEST BIT 4460 <1> 4461 <1> WAITF: 4462 <1> waitf: 4463 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4464 <1> ; 03/12/2013 4465 <1> ; 4466 <1> ; push ax ; save work register (ah) 4467 <1> ;waitf1: 4468 <1> ; use timer 1 output bits 4469 <1> ; in al, PORT_B ; read current counter output status 4470 <1> ; and al, REFRESH_BIT ; mask for refresh determine bit 4471 <1> ; cmp al, ah ; did it just change 4472 <1> ; je short waitf1 ; wait for a change in output line 4473 <1> ; ; 4474 <1> ; mov ah, al ; save new lflag state 4475 <1> ; loop waitf1 ; decrement half cycles till count end 4476 <1> ; ; 4477 <1> ; pop ax ; restore (ah) 4478 <1> ; retn ; return (cx)=0 4479 <1> 4480 <1> ; 02/02/2022 4481 <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s) 4482 <1> ; 17/12/2014 (dsectrm2.s) 4483 <1> ; WAITF 4484 <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 /// 4485 <1> ; 4486 <1> ;---WAITF----------------------------------------------------------------------- 4487 <1> ; FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR) 4488 <1> ; ENTRY: 4489 <1> ; (CX) = COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT 4490 <1> ; MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE 4491 <1> ; EXIT: 4492 <1> ; AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS) 4493 <1> ; (CX) = 0 4494 <1> ;------------------------------------------------------------------------------- 4495 <1> 4496 <1> ; Refresh period: 30 micro seconds (15-80 us) 4497 <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH) 4498 <1> 4499 <1> ;WAITF: ; DELAY FOR (CX)*15.085737 US 4500 000013AB 50 <1> push eax ; 02/02/2022 ; SAVE WORK REGISTER (AH) 4501 <1> ;push ax 4502 <1> ; 16/12/2014 4503 <1> ;shr cx, 1 ; convert to count of 30 micro seconds 4504 000013AC D1E9 <1> shr ecx, 1 ; 21/02/2015 4505 <1> ;17/12/2014 4506 <1> ;WAITF1: 4507 <1> ; IN AL, PORT_B ;061h ; READ CURRENT COUNTER OUTPUT STATUS 4508 <1> ; AND AL, REFRESH_BIT ;00010000b ; MASK FOR REFRESH DETERMINE BIT 4509 <1> ; CMP AL, AH ; DID IT JUST CHANGE 4510 <1> ; JE short WAITF1 ; WAIT FOR A CHANGE IN OUTPUT LINE 4511 <1> ; MOV AH, AL ; SAVE NEW FLAG STATE 4512 <1> ; LOOP WAITF1 ; DECREMENT HALF CYCLES TILL COUNT END 4513 <1> ; 4514 <1> ; 17/12/2014 4515 <1> ; 4516 <1> ; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999 4517 <1> ; 4518 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 4519 <1> ; INPUT: CX = number of refresh periods to wait 4520 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 4521 <1> WR_STATE_0: 4522 000013AE E461 <1> IN AL,PORT_B ; IN AL,SYS1 4523 000013B0 A810 <1> TEST AL,010H 4524 000013B2 74FA <1> JZ SHORT WR_STATE_0 4525 <1> WR_STATE_1: 4526 000013B4 E461 <1> IN AL,PORT_B ; IN AL,SYS1 4527 000013B6 A810 <1> TEST AL,010H 4528 000013B8 75FA <1> JNZ SHORT WR_STATE_1 4529 000013BA E2F2 <1> LOOP WR_STATE_0 4530 <1> ; 4531 <1> ;pop ax 4532 000013BC 58 <1> pop eax ; 02/02/2022 ; RESTORE (AH) 4533 000013BD C3 <1> RETn ; (CX) = 0 4534 <1> 4535 <1> set_cpos: 4536 <1> ; 14/06/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.2) 4537 <1> ; 27/02/2022 4538 <1> ; 23/02/2022 4539 <1> ; 02/02/2022 4540 <1> ; 27/06/2015 4541 <1> ; 01/09/2014 4542 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 4543 <1> ; 4544 <1> ; 12/12/2013 (Retro UNIX 8086 v1 - last update) 4545 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - beginning) 4546 <1> ; 4547 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4548 <1> ; 4549 <1> ; SET_CPOS 4550 <1> ; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE 4551 <1> ; NEW X-Y VALUES PASSED 4552 <1> ; INPUT 4553 <1> ; DX - ROW,COLUMN OF NEW CURSOR 4554 <1> ; BH - DISPLAY PAGE OF CURSOR 4555 <1> ; OUTPUT 4556 <1> ; CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY 4557 <1> ; 4558 000013BE 0FB6C3 <1> movzx eax, bl ; BL = video page number ; 27/06/2015 (movzx) 4559 000013C1 D0E0 <1> shl al, 1 ; word offset 4560 000013C3 BE[86670000] <1> mov esi, cursor_posn 4561 000013C8 01C6 <1> add esi, eax 4562 000013CA 668916 <1> mov [esi], dx ; save the pointer 4563 000013CD 381D[96670000] <1> cmp [active_page], bl 4564 000013D3 7531 <1> jne short m17 4565 <1> 4566 <1> ; 14/06/2022 4567 <1> ;cli ; 27/02/2022 4568 <1> 4569 <1> ;call m18 ; CURSOR SET 4570 <1> ;m17: ; SET_CPOS_RETURN 4571 <1> ; 01/09/2014 4572 <1> ; retn 4573 <1> ; DX = row/column 4574 <1> m18: 4575 000013D5 E832000000 <1> call position ; determine location in regen buffer 4576 <1> ;mov cx, [CRT_START] 4577 <1> ; 23/02/2022 4578 000013DA 0FB70D[84670000] <1> movzx ecx, word [CRT_START] 4579 000013E1 01C1 <1> add ecx, eax 4580 <1> ;add cx, ax ; add char position in regen buffer 4581 <1> ; to the start address (offset) for this page 4582 <1> ;shr cx, 1 ; divide by 2 for char only count 4583 <1> ; 23/02/2022 4584 000013E3 D1E9 <1> shr ecx, 1 4585 000013E5 B40E <1> mov ah, 14 ; register number for cursor 4586 <1> 4587 <1> ; 14/06/2022 4588 <1> ;call m16 ; output value to the 6845 4589 <1> ;sti ; 27/02/2022 4590 <1> ;retn 4591 <1> 4592 <1> ; 14/06/2022 4593 <1> ; 27/02/2022 4594 <1> ; 02/02/2022 4595 <1> ;----- THIS ROUTINE OUTPUTS THE CX REGISTER 4596 <1> ; TO THE 6845 REGISTERS NAMED IN (AH) 4597 <1> m16: 4598 <1> ; 14/06/2022 4599 000013E7 FA <1> cli ; 27/02/2022 4600 <1> ;mov dx, [addr_6845] ; address register 4601 000013E8 66BAD403 <1> mov dx, 03D4h ; I/O address of color card 4602 000013EC 88E0 <1> mov al, ah ; get value 4603 000013EE EE <1> out dx, al ; register set 4604 <1> ;inc dx ; data register 4605 <1> ; 02/02/2022 4606 000013EF FEC2 <1> inc dl 4607 000013F1 EB00 <1> jmp $+2 ; i/o delay 4608 000013F3 88E8 <1> mov al, ch ; data 4609 000013F5 EE <1> out dx, al 4610 <1> ;dec dx 4611 <1> ; 02/02/2022 4612 000013F6 FECA <1> dec dl 4613 000013F8 88E0 <1> mov al, ah 4614 000013FA FEC0 <1> inc al ; point to other data register 4615 000013FC EE <1> out dx, al ; set for second register 4616 <1> ;inc dx 4617 <1> ; 02/02/2022 4618 000013FD FEC2 <1> inc dl 4619 000013FF EB00 <1> jmp $+2 ; i/o delay 4620 00001401 88C8 <1> mov al, cl ; second data value 4621 00001403 EE <1> out dx, al 4622 <1> ; 14/06/2022 4623 00001404 FB <1> sti ; 27/02/2022 4624 <1> ;m17: 4625 00001405 C3 <1> retn 4626 <1> m17: 4627 <1> ; 14/06/2022 4628 <1> ; ('write_tty' must not return to 'putc' with cf) 4629 00001406 F8 <1> clc 4630 00001407 C3 <1> retn 4631 <1> 4632 <1> set_ctype: 4633 <1> ; 07/02/2022 4634 <1> ; 02/09/2014 (Retro UNIX 386 v1) 4635 <1> ; 4636 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4637 <1> 4638 <1> ; CH) = BITS 4-0 = START LINE FOR CURSOR 4639 <1> ; ** HARDWARE WILL ALWAYS CAUSE BLINK 4640 <1> ; ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING 4641 <1> ; OR NO CURSOR AT ALL 4642 <1> ; (CL) = BITS 4-0 = END LINE FOR CURSOR 4643 <1> 4644 <1> ;------------------------------------------------ 4645 <1> ; SET_CTYPE 4646 <1> ; THIS ROUTINE SETS THE CURSOR VALUE 4647 <1> ; INPUT 4648 <1> ; (CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE 4649 <1> ; OUTPUT 4650 <1> ; NONE 4651 <1> ;------------------------------------------------ 4652 <1> 4653 00001408 B40A <1> mov ah, 10 ; 6845 register for cursor set 4654 <1> ;mov [CURSOR_MODE], cx ; save in data area 4655 <1> ;call m16 ; output cx register 4656 <1> ;retn 4657 <1> ; 07/02/2022 4658 0000140A EBDB <1> jmp short m16 4659 <1> 4660 <1> position: 4661 <1> ; 23/02/2022 4662 <1> ; 02/02/2022 4663 <1> ; 27/06/2015 4664 <1> ; 02/09/2014 4665 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4666 <1> ; 04/12/2013 (Retro UNIX 8086 v1) 4667 <1> ; 4668 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4669 <1> ; 4670 <1> ; POSITION 4671 <1> ; THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS 4672 <1> ; OF A CHARACTER IN THE ALPHA MODE 4673 <1> ; INPUT 4674 <1> ; AX = ROW, COLUMN POSITION 4675 <1> ; OUTPUT 4676 <1> ; AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 4677 <1> 4678 <1> ; DX = ROW, COLUMN POSITION 4679 <1> ;movzx eax, byte [CRT_COLS] ; 27/06/2015 4680 0000140C 31C0 <1> xor eax, eax ; 02/09/2014 4681 0000140E B050 <1> mov al, 80 ; determine bytes to row 4682 00001410 F6E6 <1> mul dh ; row value 4683 <1> ;xor dh, dh ; 0 4684 <1> ;add ax, dx ; add column value to the result 4685 <1> ; 23/02/2022 4686 00001412 00D0 <1> add al, dl 4687 00001414 80D400 <1> adc ah, 0 4688 <1> ;shl ax, 1 ; * 2 for attribute bytes 4689 <1> ; 02/02/2022 4690 00001417 D1E0 <1> shl eax, 1 4691 <1> ; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 4692 00001419 C3 <1> retn 4693 <1> 4694 <1> find_position: 4695 <1> ; 02/02/2022 4696 <1> ; 27/06/2015 4697 <1> ; 07/09/2014 4698 <1> ; 02/09/2014 4699 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4700 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4701 0000141A 0FB6CB <1> movzx ecx, bl ; video page number ; 27/06/2015 (movzx) 4702 0000141D 89CE <1> mov esi, ecx 4703 <1> ;shl si, 1 4704 <1> ; 02/02/2022 4705 0000141F D1E6 <1> shl esi, 1 4706 00001421 668B96[86670000] <1> mov dx, [esi+cursor_posn] 4707 00001428 7409 <1> jz short p21 4708 <1> ;xor si, si 4709 <1> ; 02/02/2022 4710 0000142A 31F6 <1> xor esi, esi 4711 <1> p20: 4712 <1> ;add si, [CRT_LEN] 4713 0000142C 6681C6A00F <1> add si, 80*25*2 ; add length of buffer for one page 4714 00001431 E2F9 <1> loop p20 4715 <1> p21: 4716 00001433 6621D2 <1> and dx, dx 4717 00001436 7407 <1> jz short p22 4718 00001438 E8CFFFFFFF <1> call position ; determine location in regen in page 4719 0000143D 01C6 <1> add esi, eax ; add location to start of regen page 4720 <1> p22: 4721 <1> ;mov dx, [addr_6845] ; get base address of active display 4722 <1> ;mov dx, 03D4h ; I/O address of color card 4723 <1> ;add dx, 6 ; point at status port 4724 0000143F 66BADA03 <1> mov dx, 03DAh ; status port 4725 <1> ; cx = 0 4726 00001443 C3 <1> retn 4727 <1> 4728 <1> scroll_up: 4729 <1> ; 02/02/2022 (simplified scroll up) 4730 <1> ; ((retro unix 8086 v1 'scroll_up' in 'u9.s')) 4731 <1> ; 16/01/2016 4732 <1> ; 07/09/2014 4733 <1> ; 02/09/2014 4734 <1> ; 01/09/2014 (Retro UNIX 386 v1 - beginning) 4735 <1> ; 04/04/2014 4736 <1> ; 04/12/2013 4737 <1> ; 4738 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4739 <1> ; 4740 <1> ; SCROLL UP 4741 <1> ; THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP 4742 <1> ; ON THE SCREEN 4743 <1> ; INPUT 4744 <1> ; (AH) = CURRENT CRT MODE 4745 <1> ; (AL) = NUMBER OF ROWS TO SCROLL 4746 <1> ; (CX) = ROW/COLUMN OF UPPER LEFT CORNER 4747 <1> ; (DX) = ROW/COLUMN OF LOWER RIGHT CORNER 4748 <1> ; (BH) = ATTRIBUTE TO BE USED ON BLANKED LINE 4749 <1> ; (DS) = DATA SEGMENT 4750 <1> ; (ES) = REGEN BUFFER SEGMENT 4751 <1> ; OUTPUT 4752 <1> ; NONE -- THE REGEN BUFFER IS MODIFIED 4753 <1> ; 4754 <1> ; bh = 0 (02/09/2014) 4755 <1> ; 4756 <1> ; ((ah = 3)) 4757 <1> ; cl = left upper column 4758 <1> ; ch = left upper row 4759 <1> ; dl = right lower column 4760 <1> ; dh = right lower row 4761 <1> ; 4762 <1> ; al = line count 4763 <1> ; ah = attribute to be used on blanked line 4764 <1> ; bl = video page number (0 to 7) 4765 <1> ; 4766 <1> 4767 <1> ; 02/02/2022 'scroll_up' code 4768 <1> ; ------------------------------------------------------ 4769 <1> ; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm') 4770 <1> 4771 <1> ; INPUT: 4772 <1> ; 4773 <1> ; al = line count 4774 <1> ; (0 or 1) .. 0 -> clear video page 4775 <1> ; ah = attribute to be used on blanked line 4776 <1> ; bl = video page number (0 to 7) 4777 <1> 4778 <1> ;cli 4779 00001444 31C9 <1> xor ecx, ecx 4780 00001446 88C1 <1> mov cl, al ; line count (cl) 4781 00001448 BE00800B00 <1> mov esi, 0B8000h 4782 0000144D 3A1D[96670000] <1> cmp bl, [active_page] 4783 00001453 7411 <1> je short n1 4784 00001455 20DB <1> and bl, bl 4785 00001457 7422 <1> jz short n3 4786 00001459 88DD <1> mov ch, bl ; video page number 4787 <1> n0: 4788 0000145B 6681C6A00F <1> add si, 25*80*2 4789 00001460 FECD <1> dec ch 4790 00001462 75F7 <1> jnz short n0 4791 00001464 EB15 <1> jmp short n3 4792 <1> n1: 4793 00001466 660335[84670000] <1> add si, [CRT_START] 4794 <1> ; 4795 0000146D 66BADA03 <1> mov dx, 3DAh ; guaranteed to be color card here 4796 <1> n2: ; wait_display_enable 4797 00001471 EC <1> in al, dx ; get port 4798 00001472 A808 <1> test al, RVRT ; wait for vertical retrace 4799 00001474 74FB <1> jz short n2 ; wait_display_enable 4800 00001476 B025 <1> mov al, 25h 4801 00001478 B2D8 <1> mov dl, 0D8h ; address control port 4802 0000147A EE <1> out dx, al ; turn off video during vertical retrace 4803 <1> n3: 4804 <1> ; cl = line count 4805 <1> ; ah = attribute/color 4806 0000147B 89F7 <1> mov edi, esi 4807 0000147D 20C9 <1> and cl, cl 4808 0000147F 741F <1> jz short n6 4809 00001481 6681C6A000 <1> add si, 80*2 ; + 160 bytes 4810 00001486 66B98007 <1> mov cx, 24*80 ; 24 rows/lines 4811 0000148A F366A5 <1> rep movsw 4812 0000148D B150 <1> mov cl, 80 ; 1 row (will be cleared) 4813 <1> n4: 4814 <1> ; ah = character attribute/cocor 4815 0000148F B020 <1> mov al, 20h ; fill with blanks 4816 00001491 F366AB <1> rep stosw 4817 <1> 4818 00001494 3A1D[96670000] <1> cmp bl, [active_page] 4819 0000149A 7503 <1> jne short n5 4820 <1> 4821 <1> ;mov al, [crt_mode_set] ; get the value of mode set 4822 0000149C B029 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 4823 <1> ;mov dx, 03D8h ; always set color card port 4824 0000149E EE <1> out dx, al 4825 <1> n5: 4826 0000149F C3 <1> retn 4827 <1> n6: 4828 <1> ; clear video page 4829 000014A0 66B9D007 <1> mov cx, 25*80 ; 25 rows/lines 4830 000014A4 EBE9 <1> jmp short n4 4831 <1> 4832 <1> ; 23/02/2022 4833 <1> %if 0 ; 16/01/2016 'scroll_up' code 4834 <1> ; ------------------------------------------------------ 4835 <1> 4836 <1> ; Test Line Count 4837 <1> or al, al 4838 <1> jz short al_set 4839 <1> mov bh, dh ; subtract lower row from upper row 4840 <1> sub bh, ch 4841 <1> inc bh ; adjust difference by 1 4842 <1> cmp bh, al ; line count = amount of rows in window? 4843 <1> jne short al_set ; if not the we're all set 4844 <1> xor al, al ; otherwise set al to zero 4845 <1> al_set: 4846 <1> xor bh, bh ; 0 4847 <1> ;push ax 4848 <1> push eax ; 23/02/2022 4849 <1> ;mov esi, [crt_base] 4850 <1> mov esi, 0B8000h 4851 <1> cmp bl, [active_page] 4852 <1> jne short n0 4853 <1> ; 4854 <1> mov ax, [CRT_START] 4855 <1> add si, ax 4856 <1> jmp short n1 4857 <1> n0: 4858 <1> and bl, bl 4859 <1> jz short n1 4860 <1> mov al, bl 4861 <1> n0x: 4862 <1> ;add si, [CRT_LEN] 4863 <1> ;add esi, 80*25*2 4864 <1> add si, 80*25*2 4865 <1> dec al 4866 <1> jnz short n0x 4867 <1> n1: 4868 <1> ; Scroll position 4869 <1> ;push dx ; 23/02/2022 4870 <1> mov dx, cx ; now, upper left position in DX 4871 <1> call position 4872 <1> add esi, eax 4873 <1> mov edi, esi 4874 <1> ;pop dx ; lower right position in DX 4875 <1> sub dx, cx 4876 <1> inc dh ; dh = #rows 4877 <1> inc dl ; dl = #cols in block 4878 <1> ;pop ax ; al = line count, ah = attribute 4879 <1> pop eax ; 23/02/2022 4880 <1> xor ecx, ecx 4881 <1> mov cx, ax 4882 <1> ;mov ah, [CRT_COLS] 4883 <1> mov ah, 80 4884 <1> mul ah ; determine offset to from address 4885 <1> add ax, ax ; *2 for attribute byte 4886 <1> ; 4887 <1> ;push ax ; offset 4888 <1> ;push dx 4889 <1> ; 23/02/2022 4890 <1> push eax 4891 <1> push edx 4892 <1> ; 4893 <1> ; 04/04/2014 4894 <1> mov dx, 3DAh ; guaranteed to be color card here 4895 <1> n8: ; wait_display_enable 4896 <1> in al, dx ; get port 4897 <1> test al, RVRT ; wait for vertical retrace 4898 <1> jz short n8 ; wait_display_enable 4899 <1> mov al, 25h 4900 <1> mov dl, 0D8h ; address control port 4901 <1> out dx, al ; turn off video during vertical retrace 4902 <1> ;pop dx ; #rows, #cols 4903 <1> ;pop ax ; offset 4904 <1> ; 23/02/2022 4905 <1> pop edx 4906 <1> pop eax 4907 <1> xchg ax, cx ; 4908 <1> ; ecx = offset, al = line count, ah = attribute 4909 <1> ;n9: 4910 <1> or al, al 4911 <1> jz short n3 4912 <1> add esi, ecx ; from address for scroll 4913 <1> mov bh, dh ; #rows in block 4914 <1> sub bh, al ; #rows to be moved 4915 <1> n2: 4916 <1> ; Move rows 4917 <1> mov cl, dl ; get # of cols to move 4918 <1> push esi 4919 <1> push edi ; save start address 4920 <1> n10: 4921 <1> movsw ; move that line on screen 4922 <1> dec cl 4923 <1> jnz short n10 4924 <1> pop edi 4925 <1> pop esi ; recover addresses 4926 <1> ;mov cl, [CRT_COLS] 4927 <1> ;add cl, cl 4928 <1> ;mov ecx, 80*2 4929 <1> mov cx, 80*2 4930 <1> add esi, ecx ; next line 4931 <1> add edi, ecx 4932 <1> dec bh ; count of lines to move 4933 <1> jnz short n2 ; row loop 4934 <1> ; bh = 0 4935 <1> mov dh, al ; #rows 4936 <1> n3: 4937 <1> ; attribute in ah 4938 <1> mov al, ' ' ; fill with blanks 4939 <1> n3x: 4940 <1> ; Clear rows 4941 <1> ; dh = #rows 4942 <1> mov cl, dl ; get # of cols to clear 4943 <1> push edi ; save address 4944 <1> n11: 4945 <1> stosw ; store fill character 4946 <1> dec cl 4947 <1> jnz short n11 4948 <1> pop edi ; recover address 4949 <1> ;mov cl, [CRT_COLS] 4950 <1> ;add cl, cl 4951 <1> ;mov ecx, 80*2 4952 <1> mov cl, 80*2 4953 <1> add edi, ecx 4954 <1> dec dh 4955 <1> jnz short n3x ; 16/01/2016 4956 <1> ; 4957 <1> cmp bl, [active_page] 4958 <1> jne short n6 4959 <1> ;mov al, [CRT_MODE_SET] ; get the value of mode set 4960 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 4961 <1> mov dx, 03D8h ; always set color card port 4962 <1> out dx, al 4963 <1> n6: 4964 <1> retn 4965 <1> 4966 <1> %endif 4967 <1> 4968 <1> write_c_current: 4969 <1> ; 02/02/2022 4970 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4971 <1> ; 18/01/2014 4972 <1> ; 04/12/2013 4973 <1> ; 4974 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4975 <1> ; 4976 <1> ; WRITE_C_CURRENT 4977 <1> ; THIS ROUTINE WRITES THE CHARACTER AT 4978 <1> ; THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED 4979 <1> ; INPUT 4980 <1> ; (AH) = CURRENT CRT MODE 4981 <1> ; (BH) = DISPLAY PAGE 4982 <1> ; (CX) = COUNT OF CHARACTERS TO WRITE 4983 <1> ; (AL) = CHAR TO WRITE 4984 <1> ; (DS) = DATA SEGMENT 4985 <1> ; (ES) = REGEN SEGMENT 4986 <1> ; OUTPUT 4987 <1> ; DISPLAY REGEN BUFFER UPDATED 4988 <1> 4989 000014A6 FA <1> cli 4990 <1> ; bl = video page 4991 <1> ; al = character 4992 <1> ; ah = color/attribute 4993 <1> ;push dx 4994 <1> ;push ax ; save character & attribute/color 4995 <1> ; 02/02/2022 4996 000014A7 52 <1> push edx 4997 000014A8 50 <1> push eax 4998 000014A9 E86CFFFFFF <1> call find_position ; get regen location and port address 4999 <1> ; esi = regen location 5000 <1> ; dx = status port 5001 <1> ; 5002 <1> ; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE 5003 <1> ; 5004 <1> p41: ; wait for horizontal retrace is low or vertical 5005 000014AE FB <1> sti ; enable interrupts first 5006 000014AF 3A1D[96670000] <1> cmp bl, [active_page] 5007 000014B5 7510 <1> jne short p44 5008 000014B7 FA <1> cli ; block interrupts for single loop 5009 000014B8 EC <1> in al, dx ; get status from the adapter 5010 000014B9 A808 <1> test al, RVRT ; check for vertical retrace first 5011 000014BB 7509 <1> jnz short p43 ; Do fast write now if vertical retrace 5012 000014BD A801 <1> test al, RHRZ ; is horizontal retrace low 5013 000014BF 75ED <1> jnz short p41 ; wait until it is 5014 <1> p42: ; wait for either retrace high 5015 000014C1 EC <1> in al, dx ; get status again 5016 000014C2 A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 5017 000014C4 74FB <1> jz short p42 ; wait until either retrace active 5018 <1> p43: 5019 000014C6 FB <1> sti 5020 <1> p44: 5021 <1> ;pop ax ; restore the character (al) & attribute (ah) 5022 <1> ; 02/02/2022 5023 000014C7 58 <1> pop eax 5024 000014C8 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (crt_base) 5025 <1> ; Retro UNIX 386 v1 feature only! 5026 000014CE 668906 <1> mov [esi], ax 5027 <1> ;pop dx 5028 <1> ; 02/02/2022 5029 000014D1 5A <1> pop edx 5030 000014D2 C3 <1> retn 5031 <1> 5032 <1> %if 0 ; 02/02/2022 5033 <1> 5034 <1> set_mode: 5035 <1> ; 02/02/2022 5036 <1> ; 16/01/2016 5037 <1> ; 02/09/2014 (Retro UNIX 386 v1) 5038 <1> ; 5039 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 5040 <1> 5041 <1> ;------------------------------------------------------ 5042 <1> ; SET MODE : 5043 <1> ; THIS ROUTINE INITIALIZES THE ATTACHMENT TO : 5044 <1> ; THE SELECTED MODE, THE SCREEN IS BLANKED. : 5045 <1> ; INPUT : 5046 <1> ; (AL) - MODE SELECTED (RANGE 0-7) : 5047 <1> ; OUTPUT : 5048 <1> ; NONE : 5049 <1> ;------------------------------------------------------ 5050 <1> 5051 <1> push edi ; 16/01/2016 5052 <1> push ebx 5053 <1> push edx 5054 <1> push ecx ; 16/01/2016 5055 <1> push eax 5056 <1> 5057 <1> ;mov dx, 03D4h ; address or color card 5058 <1> mov al, 3 5059 <1> ;M8: 5060 <1> mov [CRT_MODE], al ; save mode in global variable 5061 <1> mov al, 29h 5062 <1> ;mov [CRT_MODE_SET], al ; save the mode set value 5063 <1> and al, 037h ; video off, save high resolution bit 5064 <1> ;push dx ; save port value 5065 <1> ;add dx, 4 ; point to control register 5066 <1> mov dx, 3D8h 5067 <1> out dx, al ; reset video to off to suppress rolling 5068 <1> ;pop dx 5069 <1> ;M9: 5070 <1> mov ebx, video_params ; initialization table 5071 <1> ;mov ax, [ebx+10] ; get the cursor mode from the table 5072 <1> ;xchg ah, al 5073 <1> ;mov [CURSOR_MODE], ax ; save cursor mode 5074 <1> xor ah, ah ; ah is register number during loop 5075 <1> 5076 <1> ;----- LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE 5077 <1> ; 02/02/2022 5078 <1> ; dx = 3D8h 5079 <1> xor ecx, ecx 5080 <1> mov cl, 16 5081 <1> ;mov ecx, 16 ; 16/01/2016 5082 <1> M10: ; initialization loop 5083 <1> mov al, ah ; get 6845 register number 5084 <1> out dx, al 5085 <1> ;inc dx ; point to data port 5086 <1> ; 02/02/2022 5087 <1> inc dl ; 3D9h 5088 <1> inc ah ; next register value 5089 <1> mov al, [ebx] ; get table value 5090 <1> out dx, al ; out to chip 5091 <1> inc ebx ; next in table 5092 <1> ;dec dx ; back to pointer register 5093 <1> ; 02/02/2022 5094 <1> dec dl ; 3D8h 5095 <1> loop M10 ; do the whole table 5096 <1> 5097 <1> ;----- FILL REGEN AREA WITH BLANK 5098 <1> ;xor ax, ax 5099 <1> ;mov [CRT_START], ax ; start address saved in global 5100 <1> ;mov [ACTIVE_PAGE], al ; 0 ; (re)set page value 5101 <1> ;mov ecx, 8192 ; number of words in color card 5102 <1> ; black background, light gray characeter color, space character 5103 <1> ;mov ax, 0720h ; fill char for alpha - attribute 5104 <1> ;M13: ; clear buffer 5105 <1> ;add edi, 0B8000h ; [crt_base] 5106 <1> ;rep stosw ; FILL THE REGEN BUFFER WITH BLANKS 5107 <1> 5108 <1> ;----- ENABLE VIDEO AND CORRECT PORT SETTING 5109 <1> ;mov dx, 3D4h ; mov dx, word [ADDR_6845] 5110 <1> ; prepare to output to video enable port 5111 <1> ;;add dx, 4 ; point to the mode control gerister 5112 <1> ; 02/02/2022 5113 <1> ;mov dx, 3D8h 5114 <1> ; 5115 <1> ;mov al, [CRT_MODE_SET] ; get the mode set value 5116 <1> mov al, 29h 5117 <1> out dx, al ; set video enable port 5118 <1> 5119 <1> ;----- DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY 5120 <1> ;----- AND THE NUMBER TO BE USED FOR TTY INTERFACE 5121 <1> ; 5122 <1> ;mov byte [CRT_COLS], 80h ; initialize number of columns count 5123 <1> ; 5124 <1> ;----- SET CURSOR POSITIONS 5125 <1> ;push edi 5126 <1> ;mov word [CRT_LEN], 80*25*2 5127 <1> mov edi, cursor_posn 5128 <1> mov ecx, 4 ; clear all cursor positions (16 bytes) 5129 <1> xor eax, eax 5130 <1> rep stosd ; fill with zeroes 5131 <1> ;pop edi 5132 <1> 5133 <1> ;----- SET UP OVERSCAN REGISTER 5134 <1> inc dx ; set overscan port to a default 5135 <1> mov al, 30h ; 30H valuye for all modes except 640X200 bw 5136 <1> ;M14: 5137 <1> out dx, al ; output the correct value to 3D9 port 5138 <1> ;mov [CRT_PALETTE], al ; save the value for future use 5139 <1> 5140 <1> ;----- NORMAL RETURN FROM ALL VIDEO RETURNS 5141 <1> ; 5142 <1> pop eax 5143 <1> pop ecx ; 16/01/2016 5144 <1> pop edx 5145 <1> pop ebx 5146 <1> pop edi ; 16/01/2016 5147 <1> retn 5148 <1> 5149 <1> %endif 5150 <1> 5151 <1> tty_sw: 5152 <1> ; 02/02/2022 5153 <1> ; 30/06/2015 5154 <1> ; 27/06/2015 5155 <1> ; 07/09/2014 5156 <1> ; 02/09/2014 (Retro UNIX 386 v1 - beginning) 5157 <1> ; 5158 <1> ; (Modified registers : EAX) 5159 <1> ; 5160 <1> ;mov byte [u.quant], 0 ; 04/03/2014 5161 <1> ; 5162 <1> ;act_disp_page: 5163 <1> ; 30/06/2015 5164 <1> ; 04/03/2014 (act_disp_page --> tty_sw) 5165 <1> ; 10/12/2013 5166 <1> ; 04/12/2013 5167 <1> ; 5168 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 5169 <1> ; 5170 <1> ; ACT_DISP_PAGE 5171 <1> ; THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING 5172 <1> ; THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT 5173 <1> ; INPUT 5174 <1> ; AL HAS THE NEW ACTIVE DISPLAY PAGE 5175 <1> ; OUTPUT 5176 <1> ; THE 6845 IS RESET TO DISPLAY THAT PAGE 5177 <1> 5178 <1> ;cli 5179 <1> 5180 000014D3 53 <1> push ebx 5181 <1> ;push cx 5182 <1> ;push dx 5183 <1> ; 02/02/2022 5184 000014D4 51 <1> push ecx 5185 000014D5 52 <1> push edx 5186 <1> ; 5187 000014D6 A2[96670000] <1> mov [active_page], al ; save active page value ; [ptty] 5188 <1> ;;mov cx, [CRT_LEN] ; get saved length of regen buffer 5189 <1> ;mov cx, 25*80*2 5190 <1> ; 02/02/2022 5191 000014DB B9A00F0000 <1> mov ecx, 25*80*2 5192 <1> ; 27/06/2015 5193 000014E0 0FB6D8 <1> movzx ebx, al 5194 <1> ; 02/02/2022 5195 000014E3 89D8 <1> mov eax, ebx 5196 <1> ; 5197 <1> ;cbw ; 07/09/2014 (ah=0) 5198 <1> ;mul cx ; display page times regen length 5199 <1> ; 02/02/2022 5200 000014E5 F7E1 <1> mul ecx 5201 <1> ; 10/12/2013 5202 000014E7 66A3[84670000] <1> mov [CRT_START], ax ; save start address for later 5203 <1> ;mov cx, ax ; start address to cx 5204 <1> ; 02/02/2022 5205 000014ED 89C1 <1> mov ecx, eax 5206 <1> ;;sar cx, 1 5207 <1> ;shr cx, 1 ; divide by 2 for 6845 handling 5208 <1> ; 02/02/2022 5209 000014EF D1E9 <1> shr ecx, 1 5210 000014F1 B40C <1> mov ah, 12 ; 6845 register for start address 5211 000014F3 E8EFFEFFFF <1> call m16 5212 <1> ;sal bx, 1 5213 <1> ; 01/09/2014 5214 000014F8 D0E3 <1> shl bl, 1 ; * 2 for word offset 5215 000014FA 81C3[86670000] <1> add ebx, cursor_posn 5216 00001500 668B13 <1> mov dx, [ebx] ; get cursor for this page 5217 00001503 E8CDFEFFFF <1> call m18 5218 <1> ; 5219 <1> ;pop dx 5220 <1> ;pop cx 5221 <1> ; 02/02/2022 5222 00001508 5A <1> pop edx 5223 00001509 59 <1> pop ecx 5224 0000150A 5B <1> pop ebx 5225 <1> ; 5226 <1> ;sti 5227 <1> ; 5228 0000150B C3 <1> retn 5229 <1> 5230 <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015 5231 <1> 5232 <1> ; /// End Of VIDEO FUNCTIONS /// 5233 5234 setup_rtc_int: 5235 ; source: http://wiki.osdev.org/RTC 5236 0000150C FA cli ; disable interrupts 5237 ; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6) 5238 ; in order to change this ... 5239 ; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024 5240 ; (rate must be above 2 and not over 15) 5241 ; new rate = 15 --> 32768 >> (15-1) = 2 Hz 5242 0000150D B08A mov al, 8Ah 5243 0000150F E670 out 70h, al ; set index to register A, disable NMI 5244 00001511 90 nop 5245 00001512 E471 in al, 71h ; get initial value of register A 5246 00001514 88C4 mov ah, al 5247 00001516 80E4F0 and ah, 0F0h 5248 00001519 B08A mov al, 8Ah 5249 0000151B E670 out 70h, al ; reset index to register A 5250 0000151D 88E0 mov al, ah 5251 0000151F 0C0F or al, 0Fh ; new rate (0Fh -> 15) 5252 00001521 E671 out 71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 5253 ; enable RTC interrupt 5254 00001523 B08B mov al, 8Bh ; 5255 00001525 E670 out 70h, al ; select register B and disable NMI 5256 00001527 90 nop 5257 00001528 E471 in al, 71h ; read the current value of register B 5258 0000152A 88C4 mov ah, al ; 5259 0000152C B08B mov al, 8Bh ; 5260 0000152E E670 out 70h, al ; set the index again (a read will reset the index to register B) 5261 00001530 88E0 mov al, ah ; 5262 00001532 0C40 or al, 40h ; 5263 00001534 E671 out 71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B 5264 00001536 FB sti 5265 00001537 C3 retn 5266 5267 ; Write memory information 5268 ; Temporary Code 5269 ; 06/11/2014 5270 ; 14/08/2015 5271 memory_info: 5272 00001538 A1[6C670000] mov eax, [memory_size] ; in pages 5273 0000153D 50 push eax 5274 0000153E C1E00C shl eax, 12 ; in bytes 5275 00001541 BB0A000000 mov ebx, 10 5276 00001546 89D9 mov ecx, ebx ; 10 5277 00001548 BE[D5630000] mov esi, mem_total_b_str 5278 0000154D E8AE000000 call bintdstr 5279 00001552 58 pop eax 5280 00001553 B107 mov cl, 7 5281 00001555 BE[F9630000] mov esi, mem_total_p_str 5282 0000155A E8A1000000 call bintdstr 5283 ; 14/08/2015 5284 0000155F E8B9000000 call calc_free_mem 5285 ; edx = calculated free pages 5286 ; ecx = 0 5287 00001564 A1[70670000] mov eax, [free_pages] 5288 00001569 39D0 cmp eax, edx ; calculated free mem value 5289 ; and initial free mem value are same or not? 5290 0000156B 751D jne short pmim ; print mem info with '?' if not 5291 0000156D 52 push edx ; free memory in pages 5292 ;mov eax, edx 5293 0000156E C1E00C shl eax, 12 ; convert page count 5294 ; to byte count 5295 00001571 B10A mov cl, 10 5296 00001573 BE[19640000] mov esi, free_mem_b_str 5297 00001578 E883000000 call bintdstr 5298 0000157D 58 pop eax 5299 0000157E B107 mov cl, 7 5300 00001580 BE[3D640000] mov esi, free_mem_p_str 5301 00001585 E876000000 call bintdstr 5302 pmim: 5303 0000158A BE[C3630000] mov esi, msg_memory_info 5304 pmim_nb: 5305 0000158F AC lodsb 5306 00001590 08C0 or al, al 5307 00001592 740D jz short pmim_ok 5308 00001594 56 push esi 5309 00001595 31DB xor ebx, ebx ; 0 5310 ; Video page 0 (bl=0) 5311 00001597 B407 mov ah, 07h ; Black background, 5312 ; light gray forecolor 5313 00001599 E816FDFFFF call write_tty 5314 0000159E 5E pop esi 5315 0000159F EBEE jmp short pmim_nb 5316 pmim_ok: 5317 000015A1 C3 retn 5318 5319 ; Convert binary number to hexadecimal string 5320 ; 10/05/2015 5321 ; dsectpm.s (28/02/2015) 5322 ; Retro UNIX 386 v1 - Kernel v0.2.0.6 5323 ; 01/12/2014 5324 ; 25/11/2014 5325 ; 5326 bytetohex: 5327 ; INPUT -> 5328 ; AL = byte (binary number) 5329 ; OUTPUT -> 5330 ; AX = hexadecimal string 5331 ; 5332 000015A2 53 push ebx 5333 000015A3 31DB xor ebx, ebx 5334 000015A5 88C3 mov bl, al 5335 000015A7 C0EB04 shr bl, 4 5336 000015AA 8A9B[F0150000] mov bl, [ebx+hexchrs] 5337 000015B0 86D8 xchg bl, al 5338 000015B2 80E30F and bl, 0Fh 5339 000015B5 8AA3[F0150000] mov ah, [ebx+hexchrs] 5340 000015BB 5B pop ebx 5341 000015BC C3 retn 5342 5343 wordtohex: 5344 ; INPUT -> 5345 ; AX = word (binary number) 5346 ; OUTPUT -> 5347 ; EAX = hexadecimal string 5348 ; 5349 000015BD 53 push ebx 5350 000015BE 31DB xor ebx, ebx 5351 000015C0 86E0 xchg ah, al 5352 000015C2 6650 push ax 5353 000015C4 88E3 mov bl, ah 5354 000015C6 C0EB04 shr bl, 4 5355 000015C9 8A83[F0150000] mov al, [ebx+hexchrs] 5356 000015CF 88E3 mov bl, ah 5357 000015D1 80E30F and bl, 0Fh 5358 000015D4 8AA3[F0150000] mov ah, [ebx+hexchrs] 5359 000015DA C1E010 shl eax, 16 5360 000015DD 6658 pop ax 5361 000015DF 5B pop ebx 5362 000015E0 EBC0 jmp short bytetohex 5363 ;mov bl, al 5364 ;shr bl, 4 5365 ;mov bl, [ebx+hexchrs] 5366 ;xchg bl, al 5367 ;and bl, 0Fh 5368 ;mov ah, [ebx+hexchrs] 5369 ;pop ebx 5370 ;retn 5371 5372 dwordtohex: 5373 ; INPUT -> 5374 ; EAX = dword (binary number) 5375 ; OUTPUT -> 5376 ; EDX:EAX = hexadecimal string 5377 ; 5378 000015E2 50 push eax 5379 000015E3 C1E810 shr eax, 16 5380 000015E6 E8D2FFFFFF call wordtohex 5381 000015EB 89C2 mov edx, eax 5382 000015ED 58 pop eax 5383 ;call wordtohex 5384 ;retn 5385 ; 02/01/2022 5386 000015EE EBCD jmp short wordtohex 5387 5388 ; 10/05/2015 5389 hex_digits: 5390 hexchrs: 5391 000015F0 303132333435363738- db '0123456789ABCDEF' 5392 000015F9 39414243444546 5393 5394 ; Convert binary number to decimal/numeric string 5395 ; 06/11/2014 5396 ; Temporary Code 5397 ; 5398 5399 bintdstr: 5400 ; EAX = binary number 5401 ; ESI = decimal/numeric string address 5402 ; EBX = divisor (10) 5403 ; ECX = string length (<=10) 5404 00001600 01CE add esi, ecx 5405 btdstr0: 5406 00001602 4E dec esi 5407 00001603 31D2 xor edx, edx 5408 00001605 F7F3 div ebx 5409 00001607 80C230 add dl, 30h 5410 0000160A 8816 mov [esi], dl 5411 0000160C FEC9 dec cl 5412 0000160E 740C jz short btdstr2 ; 02/01/2022 (short jump) 5413 00001610 09C0 or eax, eax 5414 00001612 75EE jnz short btdstr0 5415 btdstr1: 5416 00001614 4E dec esi 5417 00001615 C60620 mov byte [esi], 20h ; blank space 5418 00001618 FEC9 dec cl 5419 0000161A 75F8 jnz short btdstr1 5420 btdstr2: 5421 0000161C C3 retn 5422 5423 ; Calculate free memory pages on M.A.T. 5424 ; 06/11/2014 5425 ; Temporary Code 5426 ; 5427 5428 calc_free_mem: 5429 0000161D 31D2 xor edx, edx 5430 ;xor ecx, ecx 5431 ;mov cx, [mat_size] ; in pages 5432 ; 02/01/2022 5433 0000161F 8B0D[80670000] mov ecx, [mat_size] ; in pages 5434 00001625 C1E10A shl ecx, 10 ; 1024 dwords per page 5435 00001628 BE00001000 mov esi, MEM_ALLOC_TBL 5436 cfm0: 5437 0000162D AD lodsd 5438 0000162E 51 push ecx 5439 0000162F B920000000 mov ecx, 32 5440 cfm1: 5441 00001634 D1E8 shr eax, 1 5442 00001636 7301 jnc short cfm2 5443 00001638 42 inc edx 5444 cfm2: 5445 00001639 E2F9 loop cfm1 5446 0000163B 59 pop ecx 5447 0000163C E2EF loop cfm0 5448 0000163E C3 retn 5449 5450 %include 'diskio.s' ; 07/03/2015 5451 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 5452 <1> ; (re-write kernel for test by using previous version without a major defect) 5453 <1> ; **************************************************************************** 5454 <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project) 5455 <1> 5456 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 5457 <1> ; Last Modification: 18/07/2022 5458 <1> ; (Initialized Disk Parameters Data is in 'DISKDATA.INC') 5459 <1> ; (Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 5460 <1> ; 5461 <1> ; **************************************************************************** 5462 <1> ; Ref: Retro UNIX 386 v1.1 Kernel (v0.2.1.5) - DISKIO.INC 5463 <1> 5464 <1> ; ///////// DISK I/O SYSTEM /////////////// 5465 <1> 5466 <1> ; 11/07/2022 5467 <1> ;; 06/02/2015 5468 <1> ;diskette_io: 5469 <1> ; pushfd 5470 <1> ; push cs 5471 <1> ; call DISKETTE_IO_1 5472 <1> ; retn 5473 <1> 5474 <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;; 5475 <1> ;////////////////////////////////////////////////////// 5476 <1> 5477 <1> ; 11/07/2022 - (direct call instead of int 13h simulation) 5478 <1> ; Function in AL 5479 <1> ; 0 = reset 5480 <1> ; 1 = read 5481 <1> ; 2 = write 5482 <1> ; Disk drive number in DL 5483 <1> ; 0 & 1 = floppy disks 5484 <1> ; 80h .. 83h = hard disks 5485 <1> ; Sector address (LBA) in ECX 5486 <1> ; Buffer address in EBX 5487 <1> ; R/W sector count is (always) 1 5488 <1> ; 5489 <1> ; Return: 5490 <1> ; Status in AH (>0 = error code) 5491 <1> ; if CF = 1 -> error code in AH 5492 <1> ; if CF = 0 -> successful 5493 <1> ; AL = undefined 5494 <1> ; 5495 <1> ; Modified registers: (only) EAX 5496 <1> 5497 <1> ; 10/07/2022 5498 <1> ; 08/07/2022 - (diskio code has been simplified/shortened 5499 <1> ; by removing unused IBM PC-AT disk functions) 5500 <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project) 5501 <1> ; 20/02/2015 5502 <1> ; 06/02/2015 (unix386.s) 5503 <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s) 5504 <1> ; 5505 <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC) 5506 <1> ; 5507 <1> ; ADISK.EQU 5508 <1> 5509 <1> ;----- Wait control constants 5510 <1> 5511 <1> ;amount of time to wait while RESET is active. 5512 <1> 5513 <1> WAITCPU_RESET_ON EQU 21 ;Reset on must last at least 14us 5514 <1> ;at 250 KBS xfer rate. 5515 <1> ;see INTEL MCS, 1985, pg. 5-456 5516 <1> 5517 <1> WAITCPU_FOR_STATUS EQU 100 ;allow 30 microseconds for 5518 <1> ;status register to become valid 5519 <1> ;before re-reading. 5520 <1> 5521 <1> ;After sending a byte to NEC, status register may remain 5522 <1> ;incorrectly set for 24 us. 5523 <1> 5524 <1> WAITCPU_RQM_LOW EQU 24 ;number of loops to check for 5525 <1> ;RQM low. 5526 <1> 5527 <1> ; COMMON.MAC 5528 <1> ; 5529 <1> ; Timing macros 5530 <1> ; 5531 <1> 5532 <1> %macro SIODELAY 0 ; SHORT IODELAY 5533 <1> jmp short $+2 5534 <1> %endmacro 5535 <1> 5536 <1> %macro IODELAY 0 ; NORMAL IODELAY 5537 <1> jmp short $+2 5538 <1> jmp short $+2 5539 <1> %endmacro 5540 <1> 5541 <1> %macro NEWIODELAY 0 5542 <1> out 0EBh,al 5543 <1> %endmacro 5544 <1> 5545 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 5546 <1> ;;; WAIT_FOR_MEM 5547 <1> ;WAIT_FDU_INT_LO equ 017798 ; 2.5 secs in 30 micro units. 5548 <1> ;WAIT_FDU_INT_HI equ 1 5549 <1> WAIT_FDU_INT_LH equ 83334 ; 27/02/2015 (2.5 seconds waiting) 5550 <1> ;;; WAIT_FOR_PORT 5551 <1> ;WAIT_FDU_SEND_LO equ 16667 ; .5 secons in 30 us units. 5552 <1> ;WAIT_FDU_SEND_HI equ 0 5553 <1> WAIT_FDU_SEND_LH equ 16667 ; 27/02/2015 5554 <1> ;Time to wait while waiting for each byte of NEC results = .5 5555 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 5556 <1> ;WAIT_FDU_RESULTS_LO equ 16667 ; .5 seconds in 30 micro units. 5557 <1> ;WAIT_FDU_RESULTS_HI equ 0 5558 <1> WAIT_FDU_RESULTS_LH equ 16667 ; 27/02/2015 5559 <1> ;;; WAIT_REFRESH 5560 <1> ;amount of time to wait for head settle, per unit in parameter 5561 <1> ;table = 1 ms. 5562 <1> WAIT_FDU_HEAD_SETTLE equ 33 ; 1 ms in 30 micro units. 5563 <1> 5564 <1> 5565 <1> ; //////////////// DISKETTE I/O //////////////// 5566 <1> 5567 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC) 5568 <1> 5569 <1> ;---------------------------------------- 5570 <1> ; EQUATES USED BY POST AND BIOS : 5571 <1> ;---------------------------------------- 5572 <1> 5573 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 5574 <1> ;PORT_A EQU 060H ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 5575 <1> ;PORT_B EQU 061H ; PORT B READ/WRITE DIAGNOSTIC REGISTER 5576 <1> ;REFRESH_BIT EQU 00010000B ; REFRESH TEST BIT 5577 <1> 5578 <1> ;---------------------------------------- 5579 <1> ; CMOS EQUATES FOR THIS SYSTEM : 5580 <1> ;------------------------------------------------------------------------------- 5581 <1> ;CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 5582 <1> ;CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 5583 <1> ;NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 5584 <1> ; HIGH BIT OF CMOS LOCATION ADDRESS 5585 <1> 5586 <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## ----------------------------------- 5587 <1> CMOS_DISKETTE EQU 010H ; DISKETTE DRIVE TYPE BYTE ; 5588 <1> ; EQU 011H ; - RESERVED ;C 5589 <1> CMOS_DISK EQU 012H ; FIXED DISK TYPE BYTE ;H 5590 <1> ; EQU 013H ; - RESERVED ;E 5591 <1> CMOS_EQUIP EQU 014H ; EQUIPMENT WORD LOW BYTE ;C 5592 <1> 5593 <1> ;---------- DISKETTE EQUATES --------------------------------------------------- 5594 <1> INT_FLAG EQU 10000000B ; INTERRUPT OCCURRENCE FLAG 5595 <1> DSK_CHG EQU 10000000B ; DISKETTE CHANGE FLAG MASK BIT 5596 <1> DETERMINED EQU 00010000B ; SET STATE DETERMINED IN STATE BITS 5597 <1> HOME EQU 00010000B ; TRACK 0 MASK 5598 <1> SENSE_DRV_ST EQU 00000100B ; SENSE DRIVE STATUS COMMAND 5599 <1> TRK_SLAP EQU 030H ; CRASH STOP (48 TPI DRIVES) 5600 <1> QUIET_SEEK EQU 00AH ; SEEK TO TRACK 10 5601 <1> ;MAX_DRV EQU 2 ; MAX NUMBER OF DRIVES 5602 <1> HD12_SETTLE EQU 15 ; 1.2 M HEAD SETTLE TIME 5603 <1> HD320_SETTLE EQU 20 ; 320 K HEAD SETTLE TIME 5604 <1> MOTOR_WAIT EQU 37 ; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF 5605 <1> 5606 <1> ;---------- DISKETTE ERRORS ---------------------------------------------------- 5607 <1> ;TIME_OUT EQU 080H ; ATTACHMENT FAILED TO RESPOND 5608 <1> ;BAD_SEEK EQU 040H ; SEEK OPERATION FAILED 5609 <1> BAD_NEC EQU 020H ; DISKETTE CONTROLLER HAS FAILED 5610 <1> BAD_CRC EQU 010H ; BAD CRC ON DISKETTE READ 5611 <1> MED_NOT_FND EQU 00CH ; MEDIA TYPE NOT FOUND 5612 <1> DMA_BOUNDARY EQU 009H ; ATTEMPT TO DMA ACROSS 64K BOUNDARY 5613 <1> BAD_DMA EQU 008H ; DMA OVERRUN ON OPERATION 5614 <1> MEDIA_CHANGE EQU 006H ; MEDIA REMOVED ON DUAL ATTACH CARD 5615 <1> RECORD_NOT_FND EQU 004H ; REQUESTED SECTOR NOT FOUND 5616 <1> WRITE_PROTECT EQU 003H ; WRITE ATTEMPTED ON WRITE PROTECT DISK 5617 <1> BAD_ADDR_MARK EQU 002H ; ADDRESS MARK NOT FOUND 5618 <1> BAD_CMD EQU 001H ; BAD COMMAND PASSED TO DISKETTE I/O 5619 <1> 5620 <1> ;---------- DISK CHANGE LINE EQUATES ------------------------------------------- 5621 <1> NOCHGLN EQU 001H ; NO DISK CHANGE LINE AVAILABLE 5622 <1> CHGLN EQU 002H ; DISK CHANGE LINE AVAILABLE 5623 <1> 5624 <1> ;---------- MEDIA/DRIVE STATE INDICATORS --------------------------------------- 5625 <1> TRK_CAPA EQU 00000001B ; 80 TRACK CAPABILITY 5626 <1> FMT_CAPA EQU 00000010B ; MULTIPLE FORMAT CAPABILITY (1.2M) 5627 <1> DRV_DET EQU 00000100B ; DRIVE DETERMINED 5628 <1> MED_DET EQU 00010000B ; MEDIA DETERMINED BIT 5629 <1> DBL_STEP EQU 00100000B ; DOUBLE STEP BIT 5630 <1> RATE_MSK EQU 11000000B ; MASK FOR CLEARING ALL BUT RATE 5631 <1> RATE_500 EQU 00000000B ; 500 KBS DATA RATE 5632 <1> RATE_300 EQU 01000000B ; 300 KBS DATA RATE 5633 <1> RATE_250 EQU 10000000B ; 250 KBS DATA RATE 5634 <1> STRT_MSK EQU 00001100B ; OPERATION START RATE MASK 5635 <1> SEND_MSK EQU 11000000B ; MASK FOR SEND RATE BITS 5636 <1> 5637 <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY ------------------------- 5638 <1> M3D3U EQU 00000000B ; 360 MEDIA/DRIVE NOT ESTABLISHED 5639 <1> M3D1U EQU 00000001B ; 360 MEDIA,1.2DRIVE NOT ESTABLISHED 5640 <1> M1D1U EQU 00000010B ; 1.2 MEDIA/DRIVE NOT ESTABLISHED 5641 <1> MED_UNK EQU 00000111B ; NONE OF THE ABOVE 5642 <1> 5643 <1> ;---------- INTERRUPT EQUATES -------------------------------------------------- 5644 <1> ;EOI EQU 020H ; END OF INTERRUPT COMMAND TO 8259 5645 <1> ;INTA00 EQU 020H ; 8259 PORT 5646 <1> INTA01 EQU 021H ; 8259 PORT 5647 <1> INTB00 EQU 0A0H ; 2ND 8259 5648 <1> INTB01 EQU 0A1H ; 5649 <1> 5650 <1> ;------------------------------------------------------------------------------- 5651 <1> DMA08 EQU 008H ; DMA STATUS REGISTER PORT ADDRESS 5652 <1> DMA EQU 000H ; DMA CH.0 ADDRESS REGISTER PORT ADDRESS 5653 <1> DMA18 EQU 0D0H ; 2ND DMA STATUS PORT ADDRESS 5654 <1> DMA1 EQU 0C0H ; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS 5655 <1> ;------------------------------------------------------------------------------- 5656 <1> ;TIMER EQU 040H ; 8254 TIMER - BASE ADDRESS 5657 <1> 5658 <1> ;------------------------------------------------------------------------------- 5659 <1> DMA_PAGE EQU 081H ; START OF DMA PAGE REGISTERS 5660 <1> 5661 <1> ; 10/07/2022 5662 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5663 <1> ; 06/02/2015 (unix386.s, protected mode modifications) 5664 <1> ; (unix386.s <-- dsectrm2.s) 5665 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC) 5666 <1> 5667 <1> ; 10/12/2014 5668 <1> ; 5669 <1> ;int40h: 5670 <1> ; pushf 5671 <1> ; push cs 5672 <1> ; ;cli 5673 <1> ; call DISKETTE_IO_1 5674 <1> ; retn 5675 <1> 5676 <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS 5677 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 5678 <1> ; 5679 <1> 5680 <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022------------------------- 5681 <1> ; DISKETTE I/O 5682 <1> ; THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB, 5683 <1> ; 1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES. 5684 <1> ; INPUT 5685 <1> ; (AH)= 00H RESET DISKETTE SYSTEM 5686 <1> ; HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED 5687 <1> ; ON ALL DRIVES 5688 <1> ;------------------------------------------------------------------------------- 5689 <1> ; (AH)= 01H READ THE DESIRED SECTORS INTO MEMORY 5690 <1> ;------------------------------------------------------------------------------- 5691 <1> ; (AH)= 02H WRITE THE DESIRED SECTORS FROM MEMORY 5692 <1> ;------------------------------------------------------------------------------- 5693 <1> ; 5694 <1> ; REGISTERS FOR READ/WRITE 5695 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 5696 <1> ; (DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED) 5697 <1> ; (CH) - TRACK NUMBER (NOT VALUE CHECKED) 5698 <1> ; MEDIA DRIVE TRACK NUMBER 5699 <1> ; 320/360 320/360 0-39 5700 <1> ; 320/360 1.2M 0-39 5701 <1> ; 1.2M 1.2M 0-79 5702 <1> ; 720K 720K 0-79 5703 <1> ; 1.44M 1.44M 0-79 5704 <1> ; (CL) - SECTOR NUMBER (NOT VALUE CHECKED) 5705 <1> ; MEDIA DRIVE SECTOR NUMBER 5706 <1> ; 320/360 320/360 1-8/9 5707 <1> ; 320/360 1.2M 1-8/9 5708 <1> ; 1.2M 1.2M 1-15 5709 <1> ; 720K 720K 1-9 5710 <1> ; 1.44M 1.44M 1-18 5711 <1> ; (AL) NUMBER OF SECTORS (NOT VALUE CHECKED) 5712 <1> ; MEDIA DRIVE MAX NUMBER OF SECTORS 5713 <1> ; 320/360 320/360 8/9 5714 <1> ; 320/360 1.2M 8/9 5715 <1> ; 1.2M 1.2M 15 5716 <1> ; 720K 720K 9 5717 <1> ; 1.44M 1.44M 18 5718 <1> ; 5719 <1> ; (EBX) - ADDRESS OF BUFFER 5720 <1> ; 5721 <1> ;------------------------------------------------------------------------------- 5722 <1> ; OUTPUT FOR ALL FUNCTIONS 5723 <1> ; AH = STATUS OF OPERATION 5724 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS 5725 <1> ; VARIABLE IN THE DATA SEGMENT OF THIS MODULE 5726 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) 5727 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) 5728 <1> ; FOR READ/WRITE/VERIFY 5729 <1> ; DS,BX,DX,CX PRESERVED 5730 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 5731 <1> ; ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION. 5732 <1> ; ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 5733 <1> ; THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 5734 <1> ; PROBLEM IS NOT DUE TO MOTOR START-UP. 5735 <1> ;------------------------------------------------------------------------------- 5736 <1> ; 5737 <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B) 5738 <1> ; 5739 <1> ; ----------------------------------------------------------------- 5740 <1> ; | | | | | | | | | 5741 <1> ; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 5742 <1> ; | | | | | | | | | 5743 <1> ; ----------------------------------------------------------------- 5744 <1> ; | | | | | | | | 5745 <1> ; | | | | | ----------------- 5746 <1> ; | | | | | | 5747 <1> ; | | | | RESERVED | 5748 <1> ; | | | | PRESENT STATE 5749 <1> ; | | | | 000: 360K IN 360K DRIVE UNESTABLISHED 5750 <1> ; | | | | 001: 360K IN 1.2M DRIVE UNESTABLISHED 5751 <1> ; | | | | 010: 1.2M IN 1.2M DRIVE UNESTABLISHED 5752 <1> ; | | | | 011: 360K IN 360K DRIVE ESTABLISHED 5753 <1> ; | | | | 100: 360K IN 1.2M DRIVE ESTABLISHED 5754 <1> ; | | | | 101: 1.2M IN 1.2M DRIVE ESTABLISHED 5755 <1> ; | | | | 110: RESERVED 5756 <1> ; | | | | 111: NONE OF THE ABOVE 5757 <1> ; | | | | 5758 <1> ; | | | ------> MEDIA/DRIVE ESTABLISHED 5759 <1> ; | | | 5760 <1> ; | | --------------> DOUBLE STEPPING REQUIRED 5761 <1> ; | | (360K IN 1.2M DRIVE) 5762 <1> ; | | 5763 <1> ; ------------------------------> DATA TRANSFER RATE FOR THIS DRIVE: 5764 <1> ; 5765 <1> ; 00: 500 KBS 5766 <1> ; 01: 300 KBS 5767 <1> ; 10: 250 KBS 5768 <1> ; 11: RESERVED 5769 <1> ; 5770 <1> ; 5771 <1> 5772 <1> struc MD 5773 00000000 <1> .SPEC1: resb 1 ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 5774 00000001 <1> .SPEC2: resb 1 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 5775 00000002 <1> .OFF_TIM: resb 1 ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 5776 00000003 <1> .BYT_SEC: resb 1 ; 512 BYTES/SECTOR 5777 00000004 <1> .SEC_TRK: resb 1 ; EOT (LAST SECTOR ON TRACK) 5778 00000005 <1> .GAP: resb 1 ; GAP LENGTH 5779 00000006 <1> .DTL: resb 1 ; DTL 5780 00000007 <1> .GAP3: resb 1 ; GAP LENGTH FOR FORMAT 5781 00000008 <1> .FIL_BYT: resb 1 ; FILL BYTE FOR FORMAT 5782 00000009 <1> .HD_TIM: resb 1 ; HEAD SETTLE TIME (MILLISECONDS) 5783 0000000A <1> .STR_TIM: resb 1 ; MOTOR START TIME (1/8 SECONDS) 5784 0000000B <1> .MAX_TRK: resb 1 ; MAX. TRACK NUMBER 5785 0000000C <1> .RATE: resb 1 ; DATA TRANSFER RATE 5786 <1> endstruc 5787 <1> 5788 <1> BIT7OFF EQU 7FH 5789 <1> BIT7ON EQU 80H 5790 <1> 5791 <1> ; 11/07/2022 - (direct call instead of int 13h simulation) 5792 <1> ; Function in AL 5793 <1> ; 0 = reset 5794 <1> ; 1 = read 5795 <1> ; 2 = write 5796 <1> ; Disk drive number in DL 5797 <1> ; 0 & 1 = floppy disks 5798 <1> ; 80h .. 83h = hard disks 5799 <1> ; Sector address (LBA) in ECX 5800 <1> ; Buffer address in EBX 5801 <1> ; R/W sector count is (always) 1 5802 <1> ; 5803 <1> ; Return: 5804 <1> ; Status in AH (>0 = error code) 5805 <1> ; if CF = 1 -> error code in AH 5806 <1> ; if CF = 0 -> successful 5807 <1> ; AL = undefined 5808 <1> ; 5809 <1> ; Modified registers: (only) EAX 5810 <1> 5811 <1> ; 11/07/2022 5812 <1> ;;int13h: ; 16/02/2015 5813 <1> ;; 16/02/2015 - 21/02/2015 5814 <1> ;int40h: 5815 <1> ; pushfd 5816 <1> ; push cs 5817 <1> ; call DISKETTE_IO_1 5818 <1> ; retn 5819 <1> 5820 <1> DISKETTE_IO_1: 5821 <1> 5822 <1> ;sti ; INTERRUPTS BACK ON 5823 <1> ; 11/07/2022 5824 <1> ; save registers 5825 0000163F 55 <1> push ebp ; ANY 5826 <1> 5827 <1> ; 11/07/2022 5828 <1> ;push edi ; ANY 5829 <1> ;push edx ; DRIVE NUMBER (DL) 5830 <1> ;push ebx ; BUFFER ADDRESS 5831 <1> ;push ecx ; SECTOR ADDRESS (LBA) 5832 <1> ;push esi ; ANY 5833 <1> 5834 <1> ; 11/07/2022 5835 00001640 89DD <1> mov ebp, ebx ; buffer address 5836 00001642 C605[EC670000]00 <1> mov byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS 5837 00001649 0FB6FA <1> movzx edi, dl ; drive number (0 or 1) 5838 <1> 5839 0000164C 08C0 <1> or al, al ; RESET ? 5840 0000164E 7507 <1> jnz short DISKETTE_RW_1 ; NO 5841 <1> 5842 00001650 E84D010000 <1> call DSK_RESET 5843 <1> 5844 00001655 EB37 <1> jmp short DISKETTE_RW_2 5845 <1> 5846 <1> DISKETTE_RW_1: 5847 <1> ; 12/07/2022 5848 <1> ; 11/07/2022 5849 <1> ; ecx = sector address (LBA, < 2880) 5850 <1> ; ebp = buffer address 5851 <1> ; edi = drive number (0 or 1) 5852 <1> ; al = function (read = 1 or write = 2) 5853 <1> 5854 00001657 88C2 <1> mov dl, al ; * 5855 <1> convert_to_chs: 5856 <1> ;;; 5857 00001659 B004 <1> mov al, 4 ; MD.SEC_TRK ; sector per track (drv.spt) 5858 0000165B E8D9050000 <1> call GET_PARM 5859 <1> ; 12/07/2022 5860 00001660 88E6 <1> mov dh, ah ; spt 5861 00001662 89C8 <1> mov eax, ecx ; sector address (LBA) 5862 00001664 F6F6 <1> div dh ; AX/DH 5863 00001666 88E1 <1> mov cl, ah ; sector number - 1 5864 00001668 FEC1 <1> inc cl ; sector number (1 based) 5865 0000166A 28ED <1> sub ch, ch ; head = 0 5866 <1> ; heads = 2 5867 0000166C D0E8 <1> shr al, 1 ; al = al/2 5868 0000166E 80D500 <1> adc ch, 0 ; head = 1 or head = 0 5869 00001671 C1E110 <1> shl ecx, 16 5870 00001674 88C1 <1> mov cl, al ; track (cylinder) 5871 00001676 88D5 <1> mov ch, dl ; function number 5872 00001678 89CE <1> mov esi, ecx ; byte 0 = track, byte 1 = function 5873 <1> ; byte 2 = sector, byte 3 = head 5874 0000167A C1C610 <1> rol esi, 16 5875 <1> ; byte 0 = sector, byte 1 = head 5876 <1> ; byte 2 = track, byte 3 = function 5877 <1> ;;; 5878 0000167D 80FA02 <1> cmp dl, 2 ; * 5879 00001680 7407 <1> je short DISKETTE_W 5880 <1> DISKETTE_R: 5881 <1> ; dl = 1 ; * 5882 00001682 E809000000 <1> call DSK_READ 5883 00001687 EB05 <1> jmp short DISKETTE_RW_2 5884 <1> DISKETTE_W: 5885 00001689 E80F000000 <1> call DSK_WRITE 5886 <1> DISKETTE_RW_2: 5887 <1> ; 11/07/2022 5888 <1> ; Restore registers 5889 <1> ;pop esi 5890 <1> ;pop ecx 5891 <1> ;pop ebx 5892 <1> ;pop edx 5893 <1> ;pop edi 5894 <1> 5895 <1> ; 11/07/2022 5896 0000168E 5D <1> pop ebp 5897 0000168F C3 <1> retn 5898 <1> 5899 <1> ;------------------------------------------------------------------------------- 5900 <1> ; DISK_READ (AH = 01H) ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5901 <1> ; DISKETTE READ. 5902 <1> ; 5903 <1> ; ON ENTRY: EDI : DRIVE # 5904 <1> ; SI-HI : HEAD # 5905 <1> ; SI-LOW : # OF SECTORS 5906 <1> ; ES : BUFFER SEGMENT 5907 <1> ; [BP] : SECTOR # 5908 <1> ; [BP+1] : TRACK # 5909 <1> ; [BP+2] : BUFFER OFFSET 5910 <1> ; 5911 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5912 <1> ;------------------------------------------------------------------------------- 5913 <1> 5914 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5915 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 5916 <1> 5917 <1> DSK_READ: 5918 00001690 8025[EA670000]7F <1> and byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION 5919 00001697 66B846E6 <1> mov ax, 0E646h ; AX = NEC COMMAND, DMA COMMAND 5920 <1> ;call RD_WR_VF ; COMMON READ/WRITE/VERIFY 5921 <1> ;retn 5922 0000169B EB0B <1> jmp short RD_WR_VF 5923 <1> 5924 <1> ;------------------------------------------------------------------------------- 5925 <1> ; DISK_WRITE (AH = 02H) 5926 <1> ; DISKETTE WRITE. 5927 <1> ; 5928 <1> ; ON ENTRY: EDI : DRIVE # 5929 <1> ; SI-HI : HEAD # 5930 <1> ; SI-LOW : # OF SECTORS 5931 <1> ; ES : BUFFER SEGMENT 5932 <1> ; [BP] : SECTOR # 5933 <1> ; [BP+1] : TRACK # 5934 <1> ; [BP+2] : BUFFER OFFSET 5935 <1> ; 5936 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5937 <1> ;------------------------------------------------------------------------------- 5938 <1> 5939 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5940 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 5941 <1> 5942 <1> DSK_WRITE: 5943 0000169D 66B84AC5 <1> mov ax, 0C54Ah ; AX = NEC COMMAND, DMA COMMAND 5944 000016A1 800D[EA670000]80 <1> or byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION 5945 <1> ;;call RD_WR_VF ; COMMON READ/WRITE/VERIFY 5946 <1> ;;retn 5947 <1> ;jmp short RD_WR_VF 5948 <1> 5949 <1> ;------------------------------------------------------------------------------- 5950 <1> ; RD_WR_VF 5951 <1> ; COMMON READ, WRITE 5952 <1> ; MAIN LOOP FOR STATE RETRIES. 5953 <1> ; 5954 <1> ; ON ENTRY: AH = READ/WRITE NEC PARAMETER 5955 <1> ; AL = READ/WRITE DMA PARAMETER 5956 <1> ; 5957 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5958 <1> ;------------------------------------------------------------------------------- 5959 <1> 5960 <1> RD_WR_VF: 5961 <1> ; 18/07/2022 5962 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5963 000016A8 50 <1> push eax ; 24/12/2021 ; SAVE DMA, NEC PARAMETERS 5964 000016A9 E8C9010000 <1> call XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 5965 000016AE E82B020000 <1> call SETUP_STATE ; INITIALIZE START AND END RATE 5966 000016B3 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 5967 <1> DO_AGAIN: 5968 000016B4 50 <1> push eax ; 24/12/2021 ; SAVE READ/WRITE PARAMETER 5969 000016B5 E865020000 <1> call MED_CHANGE ; MEDIA CHANGE AND RESET IF CHANGED 5970 000016BA 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 5971 <1> ; 24/12/2021 5972 000016BB 7305 <1> jnc short RWV 5973 000016BD E9B6000000 <1> jmp RWV_END ; MEDIA CHANGE ERROR OR TIME-OUT 5974 <1> RWV: 5975 000016C2 50 <1> push eax ; 24/12/2021 ; SAVE READ/WRITE/VERIFY PARAMETER 5976 000016C3 8AB7[F7670000] <1> mov dh, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 5977 000016C9 80E6C0 <1> and dh, RATE_MSK ; KEEP ONLY RATE 5978 000016CC E85F050000 <1> call CMOS_TYPE ; RETURN DRIVE TYPE IN AL 5979 <1> ; 20/02/2015 5980 000016D1 7445 <1> jz short RWV_ASSUME ; ERROR IN CMOS 5981 000016D3 3C01 <1> cmp al, 1 ; 40 TRACK DRIVE? 5982 000016D5 750D <1> jne short RWV_1 ; NO, BYPASS CMOS VALIDITY CHECK 5983 000016D7 F687[F7670000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE 5984 000016DE 740F <1> jz short RWV_2 ; YES, CMOS IS CORRECT 5985 <1> ;mov al, 2 ; CHANGE TO 1.2M 5986 <1> ; 12/07/2022 5987 000016E0 FEC0 <1> inc al ; al = 2 5988 000016E2 EB0B <1> jmp short RWV_2 5989 <1> RWV_1: 5990 <1> ; 12/07/2022 5991 <1> ;jb short RWV_2 ; NO DRIVE SPECIFIED, CONTINUE 5992 000016E4 F687[F7670000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK? 5993 000016EB 7502 <1> jnz short RWV_2 ; NO, 80 TRACK 5994 000016ED B001 <1> mov al, 1 ; IT IS 40 TRACK, FIX CMOS VALUE 5995 <1> ; 12/07/2022 5996 <1> ;jmp short RWV_3 5997 <1> RWV_2: 5998 <1> ; 12/07/2022 5999 <1> ;or al, al ; TEST FOR NO DRIVE 6000 <1> ;jz short RWV_ASSUME ; ASSUME TYPE, USE MAX TRACK 6001 <1> RWV_3: 6002 <1> ; 12/07/2022 6003 <1> ;mov dl, al ; 11/07/2022 6004 000016EF E81F010000 <1> call DR_TYPE_CHECK ; RTN EBX = MEDIA/DRIVE PARAM TBL. 6005 000016F4 7222 <1> jc short RWV_ASSUME ; TYPE NOT IN TABLE (BAD CMOS) 6006 <1> 6007 <1> ;----- SEARCH FOR MEDIA/DRIVE PARAMETER TABLE 6008 <1> 6009 000016F6 57 <1> push edi ; SAVE DRIVE # 6010 <1> ;xor ebx, ebx ; EBX = INDEX TO DR_TYPE TABLE 6011 000016F7 BB[0C620000] <1> mov ebx, DR_TYPE 6012 <1> ;mov ecx, DR_CNT ; ECX = LOOP COUNT 6013 000016FC B106 <1> mov cl, DR_CNT 6014 <1> RWV_DR_SEARCH: 6015 <1> ;mov ah, [DR_TYPE+ebx] ; GET DRIVE TYPE 6016 000016FE 8A23 <1> mov ah, [ebx] 6017 00001700 80E47F <1> and ah, BIT7OFF ; MASK OUT MSB 6018 00001703 38E0 <1> cmp al, ah ; DRIVE TYPE MATCH? 6019 <1> ; 12/07/2022 6020 <1> ;cmp dl, ah ; 11/07/2022 6021 00001705 7509 <1> jne short RWV_NXT_MD ; NO, CHECK NEXT DRIVE TYPE 6022 <1> RWV_DR_FND: 6023 <1> ;mov edi, [DR_TYPE+ebx+1] ; EDI = MEDIA/DRIVE PARAMETER TABLE 6024 00001707 43 <1> inc ebx 6025 00001708 8B3B <1> mov edi, [ebx] 6026 0000170A 4B <1> dec ebx 6027 <1> RWV_MD_SEARH: 6028 0000170B 3A770C <1> cmp dh, [edi+MD.RATE] ; MATCH? 6029 0000170E 741D <1> je short RWV_MD_FND ; YES, GO GET 1ST SPECIFY BYTE 6030 <1> RWV_NXT_MD: 6031 00001710 83C305 <1> add ebx, 5 ; CHECK NEXT DRIVE TYPE 6032 <1> ;loop RWV_DR_SEARCH 6033 00001713 FEC9 <1> dec cl 6034 00001715 75E7 <1> jnz short RWV_DR_SEARCH 6035 00001717 5F <1> pop edi ; RESTORE DRIVE # 6036 <1> 6037 <1> ;----- ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED 6038 <1> 6039 <1> RWV_ASSUME: 6040 00001718 BB[2A620000] <1> mov ebx, MD_TBL1 ; POINT TO 40 TRACK 250 KBS 6041 0000171D F687[F7670000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK 6042 00001724 740A <1> jz short RWV_MD_FND1 ; MUST BE 40 TRACK 6043 00001726 BB[44620000] <1> mov ebx, MD_TBL3 ; POINT TO 80 TRACK 500 KBS 6044 0000172B EB03 <1> jmp short RWV_MD_FND1 ; GO SPECIFY PARAMTERS 6045 <1> 6046 <1> ;----- EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE 6047 <1> 6048 <1> RWV_MD_FND: 6049 0000172D 89FB <1> mov ebx, edi ; EBX = MEDIA/DRIVE PARAMETER TABLE 6050 0000172F 5F <1> pop edi ; RESTORE DRIVE # 6051 <1> 6052 <1> ;----- SEND THE SPECIFY COMMAND TO THE CONTROLLER 6053 <1> 6054 <1> RWV_MD_FND1: 6055 00001730 E824010000 <1> call SEND_SPEC_MD 6056 00001735 E851020000 <1> call CHK_LASTRATE ; ZF=1 ATTEMP RATE IS SAME AS LAST RATE 6057 0000173A 7405 <1> jz short RWV_DBL ; YES,SKIP SEND RATE COMMAND 6058 0000173C E82C020000 <1> call SEND_RATE ; SEND DATA RATE TO NEC 6059 <1> RWV_DBL: 6060 00001741 53 <1> push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 6061 00001742 E847040000 <1> call SETUP_DBL ; CHECK FOR DOUBLE STEP 6062 00001747 5B <1> pop ebx ; RESTORE ADDRESS 6063 00001748 7221 <1> jc short CHK_RET ; ERROR FROM READ ID, POSSIBLE RETRY 6064 <1> ;pop eax ; 24/12/2021 ; RESTORE NEC COMMAND 6065 <1> ;push eax ; 24/12/2021 ; SAVE NEC COMMAND 6066 <1> ; 08/07/2022 6067 0000174A 8B0424 <1> mov eax, [esp] 6068 <1> ; 18/07/2022 6069 <1> ;push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 6070 0000174D E84C020000 <1> call DMA_SETUP ; SET UP THE DMA 6071 <1> ;pop ebx 6072 00001752 58 <1> pop eax ; 24/12/2021 ; RESTORE NEC COMMAND 6073 00001753 722D <1> jc short RWV_BAC ; CHECK FOR DMA BOUNDARY ERROR 6074 00001755 50 <1> push eax ; 24/12/2021 ; SAVE NEC COMMAND 6075 00001756 53 <1> push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 6076 00001757 E88C020000 <1> call NEC_INIT ; INITIALIZE NEC 6077 0000175C 5B <1> pop ebx ; RESTORE ADDRESS 6078 0000175D 720C <1> jc short CHK_RET ; ERROR - EXIT 6079 0000175F E8B5020000 <1> call RWV_COM ; OP CODE COMMON TO READ/WRITE 6080 00001764 7205 <1> jc short CHK_RET ; ERROR - EXIT 6081 00001766 E8FC020000 <1> call NEC_TERM ; TERMINATE, GET STATUS, ETC. 6082 <1> CHK_RET: 6083 0000176B E89B030000 <1> call RETRY ; CHECK FOR, SETUP RETRY 6084 00001770 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 6085 00001771 7305 <1> jnc short RWV_END ; CY = 0 NO RETRY 6086 00001773 E93CFFFFFF <1> jmp DO_AGAIN ; CY = 1 MEANS RETRY 6087 <1> RWV_END: 6088 00001778 E846030000 <1> call DSTATE ; ESTABLISH STATE IF SUCCESSFUL 6089 0000177D E8D7030000 <1> call NUM_TRANS ; AL = NUMBER TRANSFERRED 6090 <1> RWV_BAC: 6091 <1> ; 08/07/2022 ; BAD DMA ERROR ENTRY 6092 <1> ;push eax ; 24/12/2021 ; SAVE NUMBER TRANSFERRED 6093 <1> ;CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 6094 <1> ;pop eax ; 24/12/2021 ; RESTORE NUMBER TRANSFERRED 6095 <1> ;;call SETUP_END ; VARIOUS CLEANUPS 6096 <1> ;;retn 6097 <1> ;jmp SETUP_END 6098 <1> 6099 <1> ;------------------------------------------------------------------------------- 6100 <1> ; SETUP_END 6101 <1> ; RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 6102 <1> ; AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY. 6103 <1> ; 6104 <1> ; ON EXIT: 6105 <1> ; AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6106 <1> ;------------------------------------------------------------------------------- 6107 <1> SETUP_END: 6108 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6109 <1> ;mov dl, 2 ; GET THE MOTOR WAIT PARAMETER 6110 <1> ;push ax ; SAVE NUMBER TRANSFERRED 6111 00001782 50 <1> push eax ; 24/12/2021 6112 00001783 B002 <1> mov al, 2 ; 08/07/2022 6113 00001785 E8AF040000 <1> call GET_PARM 6114 0000178A 8825[EB670000] <1> mov [MOTOR_COUNT], ah ; STORE UPON RETURN 6115 <1> ;pop ax ; RESTORE NUMBER TRANSFERRED 6116 00001790 58 <1> pop eax ; 24/12/2021 6117 00001791 8A25[EC670000] <1> mov ah, [DSKETTE_STATUS] ; GET STATUS OF OPERATION 6118 00001797 08E4 <1> or ah, ah ; CHECK FOR ERROR 6119 00001799 7406 <1> jz short NUN_ERR ; NO ERROR 6120 0000179B 30C0 <1> xor al, al ; CLEAR NUMBER RETURNED 6121 <1> ;NUN_ERR: 6122 0000179D 80FC01 <1> cmp ah, 1 ; SET THE CARRY FLAG TO INDICATE 6123 000017A0 F5 <1> cmc ; SUCCESS OR FAILURE 6124 <1> NUN_ERR: 6125 000017A1 C3 <1> retn 6126 <1> 6127 <1> ; 17/07/2022 6128 <1> ;------------------------------------------------------------------------------- 6129 <1> ; DISK_RESET (AH = 00H) 6130 <1> ; RESET THE DISKETTE SYSTEM. 6131 <1> ; 6132 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6133 <1> ;------------------------------------------------------------------------------- 6134 <1> DSK_RESET: 6135 <1> ; 17/07/2022 6136 <1> ; 12/07/2022 6137 <1> ; 11/07/2022 6138 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6139 000017A2 66BAF203 <1> mov dx, 03F2h ; ADAPTER CONTROL PORT 6140 000017A6 FA <1> cli ; NO INTERRUPTS 6141 000017A7 A0[EA670000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 6142 000017AC 243F <1> and al, 00111111b ; KEEP SELECTED AND MOTOR ON BITS 6143 000017AE C0C004 <1> rol al, 4 ; MOTOR VALUE TO HIGH NIBBLE 6144 <1> ; DRIVE SELECT TO LOW NIBBLE 6145 000017B1 0C08 <1> or al, 00001000b ; TURN ON INTERRUPT ENABLE 6146 000017B3 EE <1> out dx, al ; RESET THE ADAPTER 6147 000017B4 C605[E9670000]00 <1> mov byte [SEEK_STATUS], 0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 6148 <1> ;JMP $+2 ; WAIT FOR I/O 6149 <1> ;JMP $+2 ; WAIT FOR I/O (TO INSURE MINIMUM 6150 <1> ; PULSE WIDTH) 6151 <1> ; 19/12/2014 6152 <1> NEWIODELAY 6153 000017BB E6EB <2> out 0EBh,al 6154 <1> 6155 <1> ; 17/12/2014 6156 <1> ; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM) 6157 000017BD B915000000 <1> mov ecx, WAITCPU_RESET_ON ; cx = 21 -- Min. 14 micro seconds !? 6158 <1> wdw1: 6159 <1> NEWIODELAY ; 27/02/2015 6160 000017C2 E6EB <2> out 0EBh,al 6161 000017C4 E2FC <1> loop wdw1 6162 <1> ; 6163 000017C6 0C04 <1> or al, 00000100b ; TURN OFF RESET BIT 6164 000017C8 EE <1> out dx, al ; RESET THE ADAPTER 6165 <1> ; 16/12/2014 6166 <1> IODELAY 6167 000017C9 EB00 <2> jmp short $+2 6168 000017CB EB00 <2> jmp short $+2 6169 <1> ; 6170 <1> ;sti ; ENABLE THE INTERRUPTS 6171 000017CD E862060000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 6172 000017D2 7236 <1> jc short DR_ERR ; IF ERROR, RETURN IT 6173 <1> ;mov cx, 11000000b ; CL = EXPECTED @NEC_STATUS 6174 <1> ; 12/07/2022 6175 <1> ;xor ecx, ecx 6176 <1> ; 17/07/2022 6177 <1> ;xor ch, ch 6178 000017D4 B1C0 <1> mov cl, 11000000b 6179 <1> NXT_DRV: 6180 <1> ; 24/12/2021 6181 000017D6 51 <1> push ecx ; SAVE FOR CALL 6182 000017D7 B8[09180000] <1> mov eax, DR_POP_ERR ; LOAD NEC_OUTPUT ERROR ADDRESS 6183 000017DC 50 <1> push eax ; 6184 000017DD B408 <1> mov ah, 08h ; SENSE INTERRUPT STATUS COMMAND 6185 000017DF E846050000 <1> call NEC_OUTPUT 6186 000017E4 58 <1> pop eax ; THROW AWAY ERROR RETURN 6187 000017E5 E879060000 <1> call RESULTS ; READ IN THE RESULTS 6188 <1> ; 24/12/2021 6189 000017EA 59 <1> pop ecx ; RESTORE AFTER CALL 6190 000017EB 721D <1> jc short DR_ERR ; ERROR RETURN 6191 000017ED 3A0D[ED670000] <1> cmp cl, [NEC_STATUS] ; TEST FOR DRIVE READY TRANSITION 6192 000017F3 7515 <1> jnz short DR_ERR ; EVERYTHING OK 6193 000017F5 FEC1 <1> inc cl ; NEXT EXPECTED @NEC_STATUS 6194 000017F7 80F9C3 <1> cmp cl, 11000011b ; ALL POSSIBLE DRIVES CLEARED 6195 000017FA 76DA <1> jbe short NXT_DRV ; FALL THRU IF 11000100B OR > 6196 <1> ; 6197 000017FC E82F000000 <1> call SEND_SPEC ; SEND SPECIFY COMMAND TO NEC 6198 <1> RESBAC: 6199 00001801 E87CFFFFFF <1> call SETUP_END ; VARIOUS CLEANUPS 6200 <1> 6201 <1> ; 11/07/2022 6202 <1> ; CF = 1 -> error (error code in AH) 6203 <1> ; CF = 0 -> OK 6204 <1> 6205 <1> ;; 24/12/2021 6206 <1> ;mov ebx, esi ; GET SAVED AL TO BL 6207 <1> ;; 11/07/2022 6208 <1> ;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 6209 <1> ;rol ebx, 8 6210 <1> ; bl = function (reset = 0) 6211 <1> ; 6212 <1> ;mov al, bl ; PUT BACK FOR RETURN 6213 <1> 6214 <1> ; 11/07/2022 6215 00001806 B000 <1> mov al, 0 ; (reset function = 0) 6216 <1> 6217 00001808 C3 <1> retn 6218 <1> 6219 <1> DR_POP_ERR: 6220 <1> ; 24/12/2021 6221 00001809 59 <1> pop ecx ; CLEAR STACK 6222 <1> DR_ERR: 6223 0000180A 800D[EC670000]20 <1> or byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE 6224 00001811 EBEE <1> jmp short RESBAC ; RETURN FROM RESET 6225 <1> 6226 <1> ;------------------------------------------------------------------------------- 6227 <1> ; FNC_ERR 6228 <1> ; INVALID FUNCTION REQUESTED OR INVALID DRIVE: 6229 <1> ; SET BAD COMMAND IN STATUS. 6230 <1> ; 6231 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6232 <1> ;------------------------------------------------------------------------------- 6233 <1> 6234 <1> ; 11/07/2022 - not needed (because diskio is used by kernel only) 6235 <1> 6236 <1> ;FNC_ERR: ; INVALID FUNCTION REQUEST 6237 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6238 <1> ; ; 24/12/2021 6239 <1> ; mov eax, esi ; RESTORE AL 6240 <1> ; mov ah, BAD_CMD ; SET BAD COMMAND ERROR 6241 <1> ; mov [DSKETTE_STATUS], ah ; STORE IN DATA AREA 6242 <1> ; stc ; SET CARRY INDICATING ERROR 6243 <1> ; retn 6244 <1> 6245 <1> ;---------------------------------------------------------------- 6246 <1> ; DR_TYPE_CHECK : 6247 <1> ; CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL) : 6248 <1> ; IS SUPPORTED IN BIOS DRIVE TYPE TABLE : 6249 <1> ; ON ENTRY: : 6250 <1> ; AL = DRIVE TYPE : 6251 <1> ; ON EXIT: : 6252 <1> ; CY = 0 DRIVE TYPE SUPPORTED : 6253 <1> ; EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE : 6254 <1> ; CY = 1 DRIVE TYPE NOT SUPPORTED : 6255 <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 : 6256 <1> ;---------------------------------------------------------------- 6257 <1> DR_TYPE_CHECK: 6258 <1> ; 12/07/2022 6259 <1> ; 11/07/2022 6260 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6261 <1> ; 24/12/2021 6262 <1> ;push eax ; 11/07/2022 6263 <1> ;push ecx ; 08/07/2022 6264 <1> ;xor ebx,ebx ; EBX = INDEX TO DR_TYPE TABLE 6265 00001813 BB[0C620000] <1> mov ebx, DR_TYPE 6266 <1> ;;mov ecx, DR_CNT ; ECX = LOOP COUNT 6267 <1> ;mov cl, DR_CNT 6268 00001818 B406 <1> mov ah, DR_CNT ; 11/07/2022 6269 <1> TYPE_CHK: 6270 <1> ;;mov ah, [DR_TYPE+ebx] ; GET DRIVE TYPE 6271 <1> ;mov ah, [ebx] 6272 <1> ;cmp al, ah ; DRIVE TYPE MATCH? 6273 0000181A 3A03 <1> cmp al, [ebx] ; 11/07/2022 6274 0000181C 740E <1> je short DR_TYPE_VALID ; YES, RETURN WITH CARRY RESET 6275 <1> ; 16/02/2015 (32 bit address modification) 6276 0000181E 83C305 <1> add ebx, 5 ; CHECK NEXT DRIVE TYPE 6277 <1> ;loop TYPE_CHK 6278 <1> ;dec cl 6279 00001821 FECC <1> dec ah ; 11/07/2022 6280 00001823 75F5 <1> jnz short TYPE_CHK 6281 <1> ; 6282 00001825 BB[6B620000] <1> mov ebx, MD_TBL6 ; 1.44MB fd parameter table 6283 <1> ; Default for GET_PARM (11/12/2014) 6284 <1> ; 6285 0000182A F9 <1> stc ; DRIVE TYPE NOT FOUND IN TABLE 6286 <1> ;jmp short TYPE_RTN 6287 <1> ; 12/07/2022 6288 0000182B C3 <1> retn 6289 <1> DR_TYPE_VALID: 6290 <1> ;mov ebx, [DR_TYPE+ebx+1] ; EBX = MEDIA TABLE 6291 0000182C 43 <1> inc ebx 6292 0000182D 8B1B <1> mov ebx, [ebx] 6293 <1> TYPE_RTN: 6294 <1> ;pop ecx ; 08/07/2022 6295 <1> ; 24/12/2021 6296 <1> ;pop eax ; 11/07/2022 6297 0000182F C3 <1> retn 6298 <1> 6299 <1> ;---------------------------------------------------------------- 6300 <1> ; SEND_SPEC : 6301 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 6302 <1> ; THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER : 6303 <1> ; ON ENTRY: @DISK_POINTER = DRIVE PARAMETER TABLE : 6304 <1> ; ON EXIT: NONE : 6305 <1> ; REGISTERS ALTERED: ECX, EDX : 6306 <1> ;---------------------------------------------------------------- 6307 <1> SEND_SPEC: 6308 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6309 00001830 50 <1> push eax ; SAVE EAX 6310 00001831 B8[57180000] <1> mov eax, SPECBAC ; LOAD ERROR ADDRESS 6311 00001836 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 6312 00001837 B403 <1> mov ah, 03h ; SPECIFY COMMAND 6313 00001839 E8EC040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 6314 <1> ;sub dl, dl ; FIRST SPECIFY BYTE 6315 0000183E 28C0 <1> sub al, al ; 08/07/2022 6316 00001840 E8F4030000 <1> call GET_PARM ; GET PARAMETER TO AH 6317 00001845 E8E0040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 6318 <1> ;mov dl, 1 ; SECOND SPECIFY BYTE 6319 0000184A B001 <1> mov al, 1 ; 08/07/2022 6320 0000184C E8E8030000 <1> call GET_PARM ; GET PARAMETER TO AH 6321 00001851 E8D4040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 6322 00001856 58 <1> pop eax ; POP ERROR RETURN 6323 <1> SPECBAC: 6324 00001857 58 <1> pop eax ; RESTORE ORIGINAL EAX VALUE 6325 00001858 C3 <1> retn 6326 <1> 6327 <1> ;---------------------------------------------------------------- 6328 <1> ; SEND_SPEC_MD : 6329 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 6330 <1> ; THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (EBX) : 6331 <1> ; ON ENTRY: EBX = MEDIA/DRIVE PARAMETER TABLE : 6332 <1> ; ON EXIT: NONE : 6333 <1> ; REGISTERS ALTERED: EAX ; 11/07/2022 : 6334 <1> ;---------------------------------------------------------------- 6335 <1> SEND_SPEC_MD: 6336 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6337 <1> ;push eax ; 11/07/2022 ; SAVE RATE DATA 6338 00001859 B8[76180000] <1> mov eax, SPEC_ESBAC ; LOAD ERROR ADDRESS 6339 0000185E 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 6340 0000185F B403 <1> mov ah, 03h ; SPECIFY COMMAND 6341 00001861 E8C4040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 6342 00001866 8A23 <1> mov ah, [ebx+MD.SPEC1] ; GET 1ST SPECIFY BYTE 6343 00001868 E8BD040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 6344 0000186D 8A6301 <1> mov ah, [ebx+MD.SPEC2] ; GET SECOND SPECIFY BYTE 6345 00001870 E8B5040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 6346 00001875 58 <1> pop eax ; POP ERROR RETURN 6347 <1> SPEC_ESBAC: 6348 <1> ;pop eax ; 11/07/2022 ; RESTORE ORIGINAL EAX VALUE 6349 00001876 C3 <1> retn 6350 <1> 6351 <1> ;------------------------------------------------------------------------------- 6352 <1> ; XLAT_NEW 6353 <1> ; TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE 6354 <1> ; MODE TO NEW ARCHITECTURE. 6355 <1> ; 6356 <1> ; ON ENTRY: EDI = DRIVE # 6357 <1> ;------------------------------------------------------------------------------- 6358 <1> XLAT_NEW: 6359 <1> ; 11/07/2022 6360 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6361 <1> ;cmp edi, 1 ; VALID DRIVE 6362 <1> ;ja short XN_OUT ; IF INVALID BACK 6363 <1> ; 6364 00001877 80BF[F7670000]00 <1> cmp byte [DSK_STATE+edi], 0 ; NO DRIVE ? 6365 0000187E 7401 <1> jz short DO_DET ; IF NO DRIVE ATTEMPT DETERMINE 6366 <1> ; 6367 <1> ;mov al, [HF_CNTRL] ; DRIVE INFORMATION 6368 <1> ;mov ecx, edi ; ECX = DRIVE NUMBER 6369 <1> ;or cl, cl 6370 <1> ;jz short XN_0 ; 08/07/2022 6371 <1> ;shl cl, 2 ; CL = SHIFT COUNT, A=0, B=4 6372 <1> ;;mov al, [HF_CNTRL] ; DRIVE INFORMATION 6373 <1> ;ror al, cl ; TO LOW NIBBLE 6374 <1> ;XN_0: 6375 <1> ;and al, DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS 6376 <1> ;and byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA) 6377 <1> ;or [DSK_STATE+edi], al ; UPDATE DRIVE STATE 6378 <1> XN_OUT: 6379 00001880 C3 <1> retn 6380 <1> DO_DET: 6381 <1> ;;call DRIVE_DET ; TRY TO DETERMINE 6382 <1> ;;retn 6383 <1> ;jmp DRIVE_DET 6384 <1> 6385 <1> ;------------------------------------------------------------------------------- 6386 <1> ; DRIVE_DET 6387 <1> ; DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND 6388 <1> ; UPDATES STATE INFORMATION ACCORDINGLY. 6389 <1> ; ON ENTRY: EDI = DRIVE # 6390 <1> ;------------------------------------------------------------------------------- 6391 <1> DRIVE_DET: 6392 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6393 00001881 E8EE030000 <1> call MOTOR_ON ; TURN ON MOTOR IF NOT ALREADY ON 6394 00001886 E857050000 <1> call RECAL ; RECALIBRATE DRIVE 6395 0000188B 724E <1> jc short DD_BAC ; ASSUME NO DRIVE PRESENT 6396 0000188D B530 <1> mov ch, TRK_SLAP ; SEEK TO TRACK 48 6397 0000188F E8CF040000 <1> call SEEK 6398 00001894 7245 <1> jc short DD_BAC ; ERROR NO DRIVE 6399 00001896 B50B <1> mov ch, QUIET_SEEK+1 ; SEEK TO TRACK 10 6400 <1> SK_GIN: 6401 00001898 FECD <1> dec ch ; DECREMENT TO NEXT TRACK 6402 <1> ;push cx 6403 <1> ; 24/12/2021 6404 0000189A 51 <1> push ecx ; SAVE TRACK 6405 0000189B E8C3040000 <1> call SEEK 6406 000018A0 723A <1> jc short POP_BAC ; POP AND RETURN 6407 000018A2 B8[DC180000] <1> mov eax, POP_BAC ; LOAD NEC OUTPUT ERROR ADDRESS 6408 000018A7 50 <1> push eax 6409 000018A8 B404 <1> mov ah, SENSE_DRV_ST ; SENSE DRIVE STATUS COMMAND BYTE 6410 000018AA E87B040000 <1> call NEC_OUTPUT ; OUTPUT TO NEC 6411 <1> ; 08/07/2022 6412 000018AF 89F8 <1> mov eax, edi ; AL = DRIVE 6413 000018B1 88C4 <1> mov ah, al ; AH = DRIVE 6414 000018B3 E872040000 <1> call NEC_OUTPUT ; OUTPUT TO NEC 6415 000018B8 E8A6050000 <1> call RESULTS ; GO GET STATUS 6416 000018BD 58 <1> pop eax ; THROW AWAY ERROR ADDRESS 6417 <1> ;pop cx ; RESTORE TRACK 6418 <1> ; 24/12/2021 6419 000018BE 59 <1> pop ecx 6420 000018BF F605[ED670000]10 <1> test byte [NEC_STATUS], HOME ; TRACK 0 ? 6421 000018C6 74D0 <1> jz short SK_GIN ; GO TILL TRACK 0 6422 000018C8 08ED <1> or ch, ch ; IS HOME AT TRACK 0 6423 000018CA 7408 <1> jz short IS_80 ; MUST BE 80 TRACK DRIVE 6424 <1> 6425 <1> ; DRIVE IS A 360; SET DRIVE TO DETERMINED; 6426 <1> ; SET MEDIA TO DETERMINED AT RATE 250. 6427 <1> 6428 000018CC 808F[F7670000]94 <1> or byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250 6429 000018D3 C3 <1> retn ; ALL INFORMATION SET 6430 <1> IS_80: 6431 000018D4 808F[F7670000]01 <1> or byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY 6432 <1> DD_BAC: 6433 000018DB C3 <1> retn 6434 <1> POP_BAC: 6435 <1> ;pop cx ; THROW AWAY 6436 <1> ; 24/12/2021 6437 000018DC 59 <1> pop ecx 6438 000018DD C3 <1> retn 6439 <1> 6440 <1> ;------------------------------------------------------------------------------- 6441 <1> ; SETUP_STATE: INITIALIZES START AND END RATES. 6442 <1> ;------------------------------------------------------------------------------- 6443 <1> SETUP_STATE: 6444 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6445 000018DE F687[F7670000]10 <1> test byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ? 6446 000018E5 7537 <1> jnz short J1C ; NO STATES IF DETERMINED 6447 000018E7 66B84000 <1> mov ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE 6448 000018EB F687[F7670000]04 <1> test byte [DSK_STATE+edi], DRV_DET ; DRIVE ? 6449 000018F2 740D <1> jz short AX_SET ; DO NOT KNOW DRIVE 6450 000018F4 F687[F7670000]02 <1> test byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE? 6451 000018FB 7504 <1> jnz short AX_SET ; JUMP IF YES 6452 000018FD 66B88080 <1> mov ax, RATE_250*257 ; START A END RATE 250 FOR 360 DRIVE 6453 <1> AX_SET: 6454 00001901 80A7[F7670000]1F <1> and byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE 6455 00001908 08A7[F7670000] <1> or [DSK_STATE+edi], ah ; RATE FIRST TO TRY 6456 0000190E 8025[F4670000]F3 <1> and byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS 6457 00001915 C0C804 <1> ror al, 4 ; TO OPERATION LAST RATE LOCATION 6458 00001918 0805[F4670000] <1> or [LASTRATE], al ; LAST RATE 6459 <1> J1C: 6460 0000191E C3 <1> retn 6461 <1> 6462 <1> ;------------------------------------------------------------------------------- 6463 <1> ; MED_CHANGE 6464 <1> ; CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 6465 <1> ; CHECKS MEDIA CHANGE AGAIN. 6466 <1> ; 6467 <1> ; ON EXIT: CY = 1 MEANS MEDIA CHANGE OR TIMEOUT 6468 <1> ; @DSKETTE_STATUS = ERROR CODE 6469 <1> ;------------------------------------------------------------------------------- 6470 <1> MED_CHANGE: 6471 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6472 0000191F E897050000 <1> call READ_DSKCHNG ; READ DISK CHANCE LINE STATE 6473 00001924 7446 <1> jz short MC_OUT ; BYPASS HANDLING DISK CHANGE LINE 6474 00001926 80A7[F7670000]EF <1> and byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE 6475 <1> 6476 <1> ; THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT 6477 <1> ; ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL 6478 <1> ; BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING). 6479 <1> 6480 0000192D 89F9 <1> mov ecx, edi ; CL = DRIVE # 6481 0000192F B001 <1> mov al, 1 ; MOTOR ON BIT MASK 6482 00001931 D2E0 <1> shl al, cl ; TO APPROPRIATE POSITION 6483 00001933 F6D0 <1> not al ; KEEP ALL BUT MOTOR ON 6484 00001935 FA <1> cli ; NO INTERRUPTS 6485 00001936 2005[EA670000] <1> and [MOTOR_STATUS], al ; TURN MOTOR OFF INDICATOR 6486 0000193C FB <1> sti ; INTERRUPTS ENABLED 6487 0000193D E832030000 <1> call MOTOR_ON ; TURN MOTOR ON 6488 <1> 6489 <1> ;----- THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL 6490 <1> 6491 00001942 E85BFEFFFF <1> call DSK_RESET ; RESET NEC 6492 00001947 B501 <1> mov ch, 1 ; MOVE TO CYLINDER 1 6493 00001949 E815040000 <1> call SEEK ; ISSUE SEEK 6494 0000194E 30ED <1> xor ch, ch ; MOVE TO CYLINDER 0 6495 00001950 E80E040000 <1> call SEEK ; ISSUE SEEK 6496 00001955 C605[EC670000]06 <1> mov byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS 6497 <1> OK1: 6498 0000195C E85A050000 <1> call READ_DSKCHNG ; CHECK MEDIA CHANGED AGAIN 6499 00001961 7407 <1> jz short OK2 ; IF ACTIVE, NO DISKETTE, TIMEOUT 6500 <1> OK4: 6501 00001963 C605[EC670000]80 <1> mov byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY 6502 <1> OK2: 6503 0000196A F9 <1> stc ; MEDIA CHANGED, SET CY 6504 0000196B C3 <1> retn 6505 <1> MC_OUT: 6506 <1> ;clc ; 08/07/2022 ; NO MEDIA CHANGED, CLEAR CY 6507 0000196C C3 <1> retn 6508 <1> 6509 <1> ;------------------------------------------------------------------------------- 6510 <1> ; SEND_RATE 6511 <1> ; SENDS DATA RATE COMMAND TO NEC 6512 <1> ; ON ENTRY: EDI = DRIVE # 6513 <1> ; ON EXIT: NONE 6514 <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022 6515 <1> ;------------------------------------------------------------------------------- 6516 <1> SEND_RATE: 6517 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6518 <1> ;push ax ; SAVE REG. 6519 <1> ; 24/12/2021 6520 <1> ;push eax ; 11/07/2022 6521 0000196D 8025[F4670000]3F <1> and byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED 6522 00001974 8A87[F7670000] <1> mov al, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 6523 0000197A 24C0 <1> and al, SEND_MSK ; KEEP ONLY RATE BITS 6524 0000197C 0805[F4670000] <1> or [LASTRATE], al ; SAVE NEW RATE FOR NEXT CHECK 6525 00001982 C0C002 <1> rol al, 2 ; MOVE TO BIT OUTPUT POSITIONS 6526 00001985 66BAF703 <1> mov dx, 03F7h ; OUTPUT NEW DATA RATE 6527 00001989 EE <1> out dx, al 6528 <1> ;pop ax ; RESTORE REG. 6529 <1> ; 24/12/2021 6530 <1> ;pop eax ; 11/07/2022 6531 0000198A C3 <1> retn 6532 <1> 6533 <1> ;------------------------------------------------------------------------------- 6534 <1> ; CHK_LASTRATE 6535 <1> ; CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER. 6536 <1> ; ON ENTRY: 6537 <1> ; EDI = DRIVE # 6538 <1> ; ON EXIT: 6539 <1> ; ZF = 1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC 6540 <1> ; ZF = 0 DATA RATE IS DIFFERENT FROM LAST RATE 6541 <1> ; REGISTERS ALTERED: EAX ; 11/07/2022 6542 <1> ;------------------------------------------------------------------------------- 6543 <1> CHK_LASTRATE: 6544 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6545 <1> ;push ax ; SAVE REG. 6546 <1> ; 24/12/2021 6547 <1> ;push eax ; 11/07/2022 6548 0000198B 8A25[F4670000] <1> mov ah, [LASTRATE] ; 08/07/2022 (BugFix) 6549 <1> ; GET LAST DATA RATE SELECTED 6550 00001991 8A87[F7670000] <1> mov al, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 6551 00001997 6625C0C0 <1> and ax, SEND_MSK*257 ; KEEP ONLY RATE BITS OF BOTH 6552 0000199B 38E0 <1> cmp al, ah ; COMPARE TO PREVIOUSLY TRIED 6553 <1> ; ZF = 1 RATE IS THE SAME 6554 <1> ;pop ax ; RESTORE REG. 6555 <1> ; 24/12/2021 6556 <1> ;pop eax ; 11/07/2022 6557 0000199D C3 <1> retn 6558 <1> 6559 <1> ;------------------------------------------------------------------------------- 6560 <1> ; DMA_SETUP 6561 <1> ; THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS. 6562 <1> ; 6563 <1> ; ON ENTRY: AL = DMA COMMAND 6564 <1> ; 6565 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6566 <1> ;------------------------------------------------------------------------------- 6567 <1> 6568 <1> ; SI = Head #, # of Sectors or DASD Type 6569 <1> 6570 <1> ; 22/08/2015 6571 <1> ; 08/02/2015 - Protected Mode Modification 6572 <1> ; 06/02/2015 - 07/02/2015 6573 <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit). 6574 <1> ; (DMA Addres = Physical Address) 6575 <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address) 6576 <1> ; 6577 <1> ; 04/02/2016 (clc) 6578 <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP) 6579 <1> ; 16/12/2014 (IODELAY) 6580 <1> 6581 <1> DMA_SETUP: 6582 <1> ; 18/07/2022 6583 <1> ; 11/07/2022 6584 <1> ; ebp = buffer address 6585 <1> 6586 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6587 <1> ;; 20/02/2015 6588 <1> ;mov edx, [ebp+4] ; 11/07/2022 ; Buffer address 6589 <1> ; 08/07/2022 - not needed for Retro UNIX 386 v1.1 6590 <1> ;test edx, 0FF000000h ; 16 MB limit (22/08/2015, bugfix) 6591 <1> ;jnz short dma_bnd_err_stc 6592 <1> 6593 <1> ; al = dma command 6594 <1> 6595 <1> ; ; 18/07/2022 6596 <1> ; ; (512 bytes/sector only!) 6597 <1> ; ; 24/12/2021 6598 <1> ; push eax ; DMA command 6599 <1> ; ;push edx ; 11/07/2022 ; * 6600 <1> ; ;mov dl, 3 ; GET BYTES/SECTOR PARAMETER 6601 <1> ; mov al, 3 ; 08/07/2022 6602 <1> ; call GET_PARM ; 6603 <1> ; mov cl, ah ; SHIFT COUNT (0=128, 1=256, 2=512 ETC) 6604 <1> ; ;mov ax, si ; Sector count 6605 <1> ; ;mov ah, al ; AH = # OF SECTORS 6606 <1> ; ;sub al, al ; AL = 0, AX = # SECTORS * 256 6607 <1> ; ;shr ax, 1 ; AX = # SECTORS * 128 6608 <1> ; ;shl ax, cl ; SHIFT BY PARAMETER VALUE 6609 <1> ; ; 08/07/2022 6610 <1> ; ; 24/12/2021 6611 <1> ; ;mov edx, esi 6612 <1> ; sub eax, eax 6613 <1> ; ;mov ah, dl 6614 <1> ; ;shr eax, 1 6615 <1> ; mov al, 128 6616 <1> ; shl eax, cl 6617 <1> ; ; 6618 <1> ; dec eax ; -1 FOR DMA VALUE 6619 <1> ; mov ecx, eax 6620 <1> ; ;pop edx ; 11/07/2022 ; * 6621 <1> ; ; 24/12/2021 6622 <1> ; pop eax 6623 <1> 6624 <1> ; 18/07/2022 6625 <1> ;mov cx, 511 6626 <1> 6627 <1> ; 08/07/2022 6628 <1> ;cmp al, 42h 6629 <1> ;jne short NOT_VERF 6630 <1> ;mov edx, 0FF0000h 6631 <1> ;jmp short J33 6632 <1> ;NOT_VERF: 6633 <1> ; 11/07/2022 6634 0000199E 89EA <1> mov edx, ebp 6635 <1> ; 6636 <1> ;add dx, cx ; check for (64K) overflow 6637 <1> ; 18/07/2022 6638 <1> ; (512 bytes/sector) 6639 000019A0 6681C2FF01 <1> add dx, 511 6640 000019A5 7239 <1> jc short dma_bnd_err 6641 <1> ; 6642 <1> ;sub dx, cx ; 11/07/2022 ; Restore start address 6643 <1> J33: 6644 <1> ; 08/07/2022 6645 000019A7 FA <1> cli ; DISABLE INTERRUPTS DURING DMA SET-UP 6646 000019A8 E60C <1> out DMA+12, al ; SET THE FIRST/LAST F/F 6647 <1> IODELAY ; WAIT FOR I/O 6648 000019AA EB00 <2> jmp short $+2 6649 000019AC EB00 <2> jmp short $+2 6650 000019AE E60B <1> out DMA+11, al ; OUTPUT THE MODE BYTE 6651 <1> ;mov eax, edx ; Buffer address 6652 <1> ; 11/07/2022 6653 000019B0 89E8 <1> mov eax, ebp ; buffer address 6654 000019B2 E604 <1> out DMA+4, al ; OUTPUT LOW ADDRESS 6655 <1> IODELAY ; WAIT FOR I/O 6656 000019B4 EB00 <2> jmp short $+2 6657 000019B6 EB00 <2> jmp short $+2 6658 000019B8 88E0 <1> mov al, ah 6659 000019BA E604 <1> out DMA+4, al ; OUTPUT HIGH ADDRESS 6660 000019BC C1E810 <1> shr eax, 16 6661 <1> IODELAY ; I/O WAIT STATE 6662 000019BF EB00 <2> jmp short $+2 6663 000019C1 EB00 <2> jmp short $+2 6664 000019C3 E681 <1> out 081h, al ; OUTPUT highest BITS TO PAGE REGISTER 6665 <1> IODELAY 6666 000019C5 EB00 <2> jmp short $+2 6667 000019C7 EB00 <2> jmp short $+2 6668 <1> ;;mov ax, cx ; Byte count - 1 6669 <1> ;mov al, cl 6670 <1> ; 18/07/2022 6671 <1> ; (Byte count - 1 = 511) 6672 000019C9 B0FF <1> mov al, 0FFh ; 511-256 6673 000019CB E605 <1> out DMA+5, al ; LOW BYTE OF COUNT 6674 <1> IODELAY ; WAIT FOR I/O 6675 000019CD EB00 <2> jmp short $+2 6676 000019CF EB00 <2> jmp short $+2 6677 <1> ;;mov al, ah 6678 <1> ;mov al, ch 6679 <1> ; 18/07/2022 6680 000019D1 B001 <1> mov al, 1 ; 256 6681 000019D3 E605 <1> out DMA+5, al ; HIGH BYTE OF COUNT 6682 <1> IODELAY 6683 000019D5 EB00 <2> jmp short $+2 6684 000019D7 EB00 <2> jmp short $+2 6685 000019D9 FB <1> sti ; RE-ENABLE INTERRUPTS 6686 000019DA B002 <1> mov al, 2 ; MODE FOR 8237 6687 000019DC E60A <1> out DMA+10, al ; INITIALIZE THE DISKETTE CHANNEL 6688 <1> 6689 000019DE F8 <1> clc ; 04/02/2016 6690 <1> 6691 000019DF C3 <1> retn 6692 <1> 6693 <1> ; 18/07/2022 6694 <1> ;dma_bnd_err_stc: 6695 <1> ; stc 6696 <1> 6697 <1> dma_bnd_err: 6698 000019E0 C605[EC670000]09 <1> mov byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 6699 000019E7 C3 <1> retn ; CY SET BY ABOVE IF ERROR 6700 <1> 6701 <1> ;------------------------------------------------------------------------------- 6702 <1> ; NEC_INIT 6703 <1> ; THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES 6704 <1> ; THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION. 6705 <1> ; 6706 <1> ; ON ENTRY: AH = NEC COMMAND TO BE PERFORMED 6707 <1> ; 6708 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6709 <1> ;------------------------------------------------------------------------------- 6710 <1> NEC_INIT: 6711 <1> ; 11/07/2022 6712 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6713 <1> ;push ax ; SAVE NEC COMMAND 6714 <1> ; 24/12/2021 6715 000019E8 50 <1> push eax 6716 000019E9 E886020000 <1> call MOTOR_ON ; TURN MOTOR ON FOR SPECIFIC DRIVE 6717 <1> 6718 <1> ;----- DO THE SEEK OPERATION 6719 <1> 6720 <1> ;mov ch, [ebp+1] ; CH = TRACK # 6721 <1> ; 11/07/2022 6722 000019EE 89F1 <1> mov ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector 6723 000019F0 C1E908 <1> shr ecx, 8 6724 <1> ; ch = track # 6725 <1> 6726 000019F3 E86B030000 <1> call SEEK ; MOVE TO CORRECT TRACK 6727 <1> ;pop ax ; RECOVER COMMAND 6728 <1> ; 24/12/2021 6729 000019F8 58 <1> pop eax 6730 000019F9 721D <1> jc short ER_1 ; ERROR ON SEEK 6731 000019FB BB[181A0000] <1> mov ebx, ER_1 ; LOAD ERROR ADDRESS 6732 00001A00 53 <1> push ebx ; PUSH NEC_OUT ERROR RETURN 6733 <1> 6734 <1> ;----- SEND OUT THE PARAMETERS TO THE CONTROLLER 6735 <1> 6736 00001A01 E824030000 <1> call NEC_OUTPUT ; OUTPUT THE OPERATION COMMAND 6737 00001A06 89F0 <1> mov eax, esi ; AH = HEAD # 6738 00001A08 89FB <1> mov ebx, edi ; BL = DRIVE # 6739 00001A0A C0E402 <1> sal ah, 2 ; MOVE IT TO BIT 2 6740 00001A0D 80E404 <1> and ah, 00000100b ; ISOLATE THAT BIT 6741 00001A10 08DC <1> or ah, bl ; OR IN THE DRIVE NUMBER 6742 00001A12 E813030000 <1> call NEC_OUTPUT ; FALL THRU CY SET IF ERROR 6743 00001A17 5B <1> pop ebx ; THROW AWAY ERROR RETURN 6744 <1> ER_1: 6745 00001A18 C3 <1> retn 6746 <1> 6747 <1> ;------------------------------------------------------------------------------- 6748 <1> ; RWV_COM 6749 <1> ; THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 6750 <1> ; READ/WRITE/VERIFY OPERATIONS. 6751 <1> ; 6752 <1> ; ON ENTRY: EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE 6753 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6754 <1> ;------------------------------------------------------------------------------- 6755 <1> RWV_COM: 6756 <1> ; 11/07/2022 6757 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6758 00001A19 B8[661A0000] <1> mov eax, ER_2 ; LOAD ERROR ADDRESS 6759 00001A1E 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 6760 <1> ;mov ah, [ebp+1] ; OUTPUT TRACK # 6761 <1> ; 11/07/2022 6762 00001A1F 89F0 <1> mov eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track 6763 00001A21 C1E808 <1> shr eax, 8 6764 <1> ; ah = track # 6765 00001A24 E801030000 <1> call NEC_OUTPUT 6766 00001A29 89F0 <1> mov eax, esi ; OUTPUT HEAD # 6767 <1> ; ah = head # 6768 00001A2B E8FA020000 <1> call NEC_OUTPUT 6769 <1> ;mov ah, [ebp] ; OUTPUT SECTOR # 6770 00001A30 89F0 <1> mov eax, esi 6771 00001A32 88C4 <1> mov ah, al 6772 <1> ; ah = sector # 6773 00001A34 E8F1020000 <1> CALL NEC_OUTPUT 6774 <1> ;mov dl, 3 ; BYTES/SECTOR PARAMETER FROM BLOCK 6775 00001A39 B003 <1> mov al, 3 ; 08/07/2022 6776 00001A3B E8F9010000 <1> call GET_PARM ; .. TO THE NEC 6777 00001A40 E8E5020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 6778 <1> ;mov dl, 4 ; EOT PARAMETER FROM BLOCK 6779 00001A45 B004 <1> mov al, 4 ; 08/07/2022 6780 00001A47 E8ED010000 <1> call GET_PARM ; .. TO THE NEC 6781 00001A4C E8D9020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 6782 00001A51 8A6305 <1> mov ah, [ebx+MD.GAP] ; GET GAP LENGTH 6783 <1> _R15: 6784 00001A54 E8D1020000 <1> call NEC_OUTPUT 6785 <1> ;mov dl, 6 ; DTL PARAMETER PROM BLOCK 6786 00001A59 B006 <1> mov al, 6 ; 08/07/2022 6787 00001A5B E8D9010000 <1> call GET_PARM ; .. TO THE NEC 6788 00001A60 E8C5020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 6789 00001A65 58 <1> pop eax ; THROW AWAY ERROR EXIT 6790 <1> ER_2: 6791 00001A66 C3 <1> retn 6792 <1> 6793 <1> ;------------------------------------------------------------------------------- 6794 <1> ; NEC_TERM 6795 <1> ; THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 6796 <1> ; FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION. 6797 <1> ; 6798 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6799 <1> ;------------------------------------------------------------------------------- 6800 <1> 6801 <1> NEC_TERM: 6802 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6803 <1> 6804 <1> ;----- LET THE OPERATION HAPPEN 6805 <1> 6806 00001A67 56 <1> push esi ; SAVE HEAD #, # OF SECTORS 6807 00001A68 E8C7030000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 6808 00001A6D 9C <1> pushfd ; 24/12/2021 6809 00001A6E E8F0030000 <1> call RESULTS ; GET THE NEC STATUS 6810 00001A73 724B <1> jc short SET_END_POP 6811 00001A75 9D <1> popfd ; 24/12/2021 6812 00001A76 723E <1> jc short SET_END ; LOOK FOR ERROR 6813 <1> 6814 <1> ;----- CHECK THE RESULTS RETURNED BY THE CONTROLLER 6815 <1> 6816 00001A78 FC <1> cld ; SET THE CORRECT DIRECTION 6817 00001A79 BE[ED670000] <1> mov esi, NEC_STATUS ; POINT TO STATUS FIELD 6818 00001A7E AC <1> lodsb ; GET ST0 6819 00001A7F 24C0 <1> and al, 11000000b ; TEST FOR NORMAL TERMINATION 6820 00001A81 7433 <1> jz short SET_END 6821 00001A83 3C40 <1> cmp al, 01000000b ; TEST FOR ABNORMAL TERMINATION 6822 00001A85 7527 <1> jnz short J18 ; NOT ABNORMAL, BAD NEC 6823 <1> 6824 <1> ;----- ABNORMAL TERMINATION, FIND OUT WHY 6825 <1> 6826 00001A87 AC <1> lodsb ; GET ST1 6827 00001A88 D0E0 <1> sal al, 1 ; TEST FOR EDT FOUND 6828 00001A8A B404 <1> mov ah, RECORD_NOT_FND 6829 00001A8C 7222 <1> jc short J19 6830 00001A8E C0E002 <1> sal al, 2 6831 00001A91 B410 <1> mov ah, BAD_CRC 6832 00001A93 721B <1> jc short J19 6833 00001A95 D0E0 <1> sal al, 1 ; TEST FOR DMA OVERRUN 6834 00001A97 B408 <1> mov ah, BAD_DMA 6835 00001A99 7215 <1> jc short J19 6836 00001A9B C0E002 <1> sal al, 2 ; TEST FOR RECORD NOT FOUND 6837 00001A9E B404 <1> mov ah, RECORD_NOT_FND 6838 00001AA0 720E <1> jc short J19 6839 00001AA2 D0E0 <1> sal al, 1 6840 00001AA4 B403 <1> mov ah, WRITE_PROTECT ; TEST FOR WRITE_PROTECT 6841 00001AA6 7208 <1> jc short J19 6842 00001AA8 D0E0 <1> sal al, 1 ; TEST MISSING ADDRESS MARK 6843 00001AAA B402 <1> mov ah, BAD_ADDR_MARK 6844 00001AAC 7202 <1> jc short J19 6845 <1> 6846 <1> ;----- NEC MUST HAVE FAILED 6847 <1> J18: 6848 00001AAE B420 <1> mov ah, BAD_NEC 6849 <1> J19: 6850 00001AB0 0825[EC670000] <1> or [DSKETTE_STATUS], ah 6851 <1> SET_END: 6852 00001AB6 803D[EC670000]01 <1> cmp byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION 6853 00001ABD F5 <1> cmc 6854 00001ABE 5E <1> pop esi 6855 00001ABF C3 <1> retn ; RESTORE HEAD #, # OF SECTORS 6856 <1> 6857 <1> SET_END_POP: 6858 00001AC0 9D <1> popfd ; 24/12/2021 6859 00001AC1 EBF3 <1> jmp short SET_END 6860 <1> 6861 <1> ;------------------------------------------------------------------------------- 6862 <1> ; DSTATE: ESTABLISH STATE UPON SUCCESSFUL OPERATION. 6863 <1> ;------------------------------------------------------------------------------- 6864 <1> DSTATE: 6865 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6866 00001AC3 803D[EC670000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR 6867 00001ACA 753E <1> jne short SETBAC ; IF ERROR JUMP 6868 00001ACC 808F[F7670000]10 <1> or byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED 6869 00001AD3 F687[F7670000]04 <1> test byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ? 6870 00001ADA 752E <1> jnz short SETBAC ; IF DETERMINED NO TRY TO DETERMINE 6871 00001ADC 8A87[F7670000] <1> mov al, [DSK_STATE+edi] ; LOAD STATE 6872 00001AE2 24C0 <1> and al, RATE_MSK ; KEEP ONLY RATE 6873 00001AE4 3C80 <1> cmp al, RATE_250 ; RATE 250 ? 6874 00001AE6 751B <1> jne short M_12 ; NO, MUST BE 1.2M OR 1.44M DRIVE 6875 <1> 6876 <1> ;----- CHECK IF IT IS 1.44M 6877 <1> 6878 00001AE8 E843010000 <1> call CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 6879 <1> ;;20/02/2015 6880 <1> ;;jc short M_12 ; CMOS BAD 6881 00001AED 7414 <1> jz short M_12 ;; 20/02/2015 6882 00001AEF 3C04 <1> cmp al, 4 ; 1.44MB DRIVE ? 6883 00001AF1 7410 <1> je short M_12 ; YES 6884 <1> M_720: 6885 00001AF3 80A7[F7670000]FD <1> and byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY 6886 00001AFA 808F[F7670000]04 <1> or byte [DSK_STATE+edi], DRV_DET ; MARK DRIVE DETERMINED 6887 00001B01 EB07 <1> jmp short SETBAC ; BACK 6888 <1> M_12: 6889 00001B03 808F[F7670000]06 <1> or byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 6890 <1> ; TURN ON DETERMINED & FMT CAPA 6891 <1> SETBAC: 6892 00001B0A C3 <1> retn 6893 <1> 6894 <1> ;------------------------------------------------------------------------------- 6895 <1> ; RETRY 6896 <1> ; DETERMINES WHETHER A RETRY IS NECESSARY. 6897 <1> ; IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY. 6898 <1> ; 6899 <1> ; ON EXIT: CY = 1 FOR RETRY, CY = 0 FOR NO RETRY 6900 <1> ;------------------------------------------------------------------------------- 6901 <1> RETRY: 6902 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6903 00001B0B 803D[EC670000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION 6904 00001B12 7444 <1> je short NO_RETRY ; SUCCESSFUL OPERATION 6905 00001B14 803D[EC670000]80 <1> cmp byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY 6906 00001B1B 743B <1> je short NO_RETRY 6907 00001B1D 8AA7[F7670000] <1> mov ah, [DSK_STATE+edi] ; GET MEDIA STATE OF DRIVE 6908 00001B23 F6C410 <1> test ah, MED_DET ; ESTABLISHED/DETERMINED ? 6909 00001B26 7530 <1> jnz short NO_RETRY ; IF ESTABLISHED STATE THEN TRUE ERROR 6910 00001B28 80E4C0 <1> and ah, RATE_MSK ; ISOLATE RATE 6911 00001B2B 8A2D[F4670000] <1> mov ch, [LASTRATE] ; GET START OPERATION STATE 6912 00001B31 C0C504 <1> rol ch, 4 ; TO CORRESPONDING BITS 6913 00001B34 80E5C0 <1> and ch, RATE_MSK ; ISOLATE RATE BITS 6914 00001B37 38E5 <1> cmp ch, ah ; ALL RATES TRIED 6915 00001B39 741D <1> je short NO_RETRY ; IF YES, THEN TRUE ERROR 6916 <1> 6917 <1> ; SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE 6918 <1> ; 00000000B (500) -> 10000000B (250) 6919 <1> ; 10000000B (250) -> 01000000B (300) 6920 <1> ; 01000000B (300) -> 00000000B (500) 6921 <1> 6922 00001B3B 80FC01 <1> cmp ah, RATE_500+1 ; SET CY FOR RATE 500 6923 00001B3E D0DC <1> rcr ah, 1 ; TO NEXT STATE 6924 00001B40 80E4C0 <1> and ah, RATE_MSK ; KEEP ONLY RATE BITS 6925 00001B43 80A7[F7670000]1F <1> and byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) 6926 <1> ; RATE, DBL STEP OFF 6927 00001B4A 08A7[F7670000] <1> or [DSK_STATE+edi], ah ; TURN ON NEW RATE 6928 00001B50 C605[EC670000]00 <1> mov byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY 6929 00001B57 F9 <1> stc ; SET CARRY FOR RETRY 6930 <1> NO_RETRY: ; 08/07/2022 6931 00001B58 C3 <1> retn ; RETRY RETURN 6932 <1> 6933 <1> ;NO_RETRY: 6934 <1> ;clc ; CLEAR CARRY NO RETRY 6935 <1> ;RETn ; NO RETRY RETURN 6936 <1> 6937 <1> ;------------------------------------------------------------------------------- 6938 <1> ; NUM_TRANS 6939 <1> ; THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE 6940 <1> ; ACTUALLY TRANSFERRED TO/FROM THE DISKETTE. 6941 <1> ; 6942 <1> ; ON ENTRY: [BP+1] = TRACK 6943 <1> ; SI-HI = HEAD 6944 <1> ; [BP] = START SECTOR 6945 <1> ; 6946 <1> ; ON EXIT: AL = NUMBER ACTUALLY TRANSFERRED 6947 <1> ;------------------------------------------------------------------------------- 6948 <1> NUM_TRANS: 6949 <1> ; 11/07/2022 6950 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6951 00001B59 30C0 <1> xor al, al ; CLEAR FOR ERROR 6952 00001B5B 803D[EC670000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR 6953 <1> ; 24/12/2021 6954 00001B62 7529 <1> jne short NT_OUT ; IF ERROR 0 TRANSFERRED 6955 <1> ;mov dl, 4 ; SECTORS/TRACK OFFSET TO DL 6956 00001B64 B004 <1> mov al, 4 ; 08/07/2022 6957 00001B66 E8CE000000 <1> call GET_PARM ; AH = SECTORS/TRACK 6958 <1> ;mov bl, [NEC_STATUS+5] ; GET ENDING SECTOR 6959 00001B6B A0[F2670000] <1> mov al, [NEC_STATUS+5] 6960 00001B70 89F1 <1> mov ecx, esi ; CH = HEAD # STARTED 6961 00001B72 88CB <1> mov bl, cl ; 11/07/2022 ; sector # 6962 00001B74 3A2D[F1670000] <1> cmp ch, [NEC_STATUS+4] ; GET HEAD ENDED UP ON 6963 00001B7A 750D <1> jne short DIF_HD ; IF ON SAME HEAD, THEN NO ADJUST 6964 <1> ; 11/07/2022 6965 <1> ;mov ch, [NEC_STATUS+3] ; GET TRACK ENDED UP ON 6966 <1> ;cmp ch, [ebp+1] ; IS IT ASKED FOR TRACK 6967 <1> ;jz short SAME_TR ; IF SAME TRACK NO INCREASE 6968 00001B7C C1E908 <1> shr ecx, 8 ; byte 3 = track # --> byte 2 6969 00001B7F 3A2D[F0670000] <1> cmp ch, [NEC_STATUS+3] 6970 00001B85 7404 <1> je short SAME_TRK 6971 <1> ; 11/07/2022 6972 <1> ;add bl, ah ; ADD SECTORS/TRACK 6973 00001B87 00E0 <1> add al, ah 6974 <1> DIF_HD: 6975 <1> ;add bl, ah ; ADD SECTORS/TRACK 6976 00001B89 00E0 <1> add al, ah 6977 <1> SAME_TRK: 6978 <1> ;sub bl, [ebp] ; SUBTRACT START FROM END 6979 <1> ;mov al, bl ; TO AL 6980 00001B8B 28D8 <1> sub al, bl 6981 <1> NT_OUT: 6982 00001B8D C3 <1> retn 6983 <1> 6984 <1> ;------------------------------------------------------------------------------- 6985 <1> ; SETUP_DBL 6986 <1> ; CHECK DOUBLE STEP. 6987 <1> ; 6988 <1> ; ON ENTRY : EDI = DRIVE # 6989 <1> ; 6990 <1> ; ON EXIT : CY = 1 MEANS ERROR 6991 <1> ;------------------------------------------------------------------------------- 6992 <1> SETUP_DBL: 6993 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6994 00001B8E 8AA7[F7670000] <1> mov ah, [DSK_STATE+edi] ; ACCESS STATE 6995 00001B94 F6C410 <1> test ah, MED_DET ; ESTABLISHED STATE ? 6996 00001B97 7578 <1> jnz short NO_DBL ; IF ESTABLISHED THEN DOUBLE DONE 6997 <1> 6998 <1> ;----- CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE 6999 <1> 7000 00001B99 C605[E9670000]00 <1> mov byte [SEEK_STATUS], 0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 7001 00001BA0 E8CF000000 <1> call MOTOR_ON ; ENSURE MOTOR STAY ON 7002 00001BA5 B500 <1> mov ch, 0 ; LOAD TRACK 0 7003 00001BA7 E8B7010000 <1> call SEEK ; SEEK TO TRACK 0 7004 00001BAC E862000000 <1> call READ_ID ; READ ID FUNCTION 7005 00001BB1 7243 <1> jc short SD_ERR ; IF ERROR NO TRACK 0 7006 <1> 7007 <1> ;----- INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS) 7008 <1> 7009 00001BB3 66B95004 <1> mov cx, 0450h ; START, MAX TRACKS 7010 00001BB7 F687[F7670000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY 7011 00001BBE 7402 <1> jz short CNT_OK ; IF NOT COUNT IS SETUP 7012 00001BC0 B1A0 <1> mov cl, 0A0h ; MAXIMUM TRACK 1.2 MB 7013 <1> 7014 <1> ; ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS, 7015 <1> ; MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT 7016 <1> ; THEN SET DOUBLE STEP ON. 7017 <1> 7018 <1> CNT_OK: 7019 00001BC2 C605[EB670000]FF <1> mov byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 7020 <1> ; 24/12/2021 7021 00001BC9 51 <1> push ecx ; SAVE TRACK, COUNT 7022 00001BCA C605[EC670000]00 <1> mov byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS 7023 00001BD1 31C0 <1> xor eax, eax ; CLEAR EAX 7024 00001BD3 D0ED <1> shr ch, 1 ; HALVE TRACK, CY = HEAD 7025 00001BD5 C0D003 <1> rcl al, 3 ; AX = HEAD IN CORRECT BIT 7026 <1> ; 24/12/2021 7027 00001BD8 50 <1> push eax ; SAVE HEAD 7028 00001BD9 E885010000 <1> call SEEK ; SEEK TO TRACK 7029 <1> ; 24/12/2021 7030 00001BDE 58 <1> pop eax ; RESTORE HEAD 7031 00001BDF 09C7 <1> or edi, eax ; DI = HEAD OR'ED DRIVE 7032 00001BE1 E82D000000 <1> call READ_ID ; READ ID HEAD 0 7033 00001BE6 9C <1> pushf ; SAVE RETURN FROM READ_ID 7034 00001BE7 6681E7FB00 <1> and di, 11111011b ; TURN OFF HEAD 1 BIT 7035 00001BEC 9D <1> popf ; RESTORE ERROR RETURN 7036 <1> ; 24/12/2021 7037 00001BED 59 <1> pop ecx ; RESTORE COUNT 7038 00001BEE 7308 <1> jnc short DO_CHK ; IF OK, ASKED = RETURNED TRACK ? 7039 00001BF0 FEC5 <1> inc ch ; INC FOR NEXT TRACK 7040 00001BF2 38CD <1> cmp ch, cl ; REACHED MAXIMUM YET 7041 00001BF4 75CC <1> jnz short CNT_OK ; CONTINUE TILL ALL TRIED 7042 <1> 7043 <1> ;----- FALL THRU, READ ID FAILED FOR ALL TRACKS 7044 <1> 7045 <1> SD_ERR: 7046 00001BF6 F9 <1> stc ; SET CARRY FOR ERROR 7047 00001BF7 C3 <1> retn ; SETUP_DBL ERROR EXIT 7048 <1> 7049 <1> DO_CHK: 7050 00001BF8 8A0D[F0670000] <1> mov cl, [NEC_STATUS+3] ; LOAD RETURNED TRACK 7051 00001BFE 888F[F9670000] <1> mov [DSK_TRK+edi], cl ; STORE TRACK NUMBER 7052 00001C04 D0ED <1> shr ch, 1 ; HALVE TRACK 7053 00001C06 38CD <1> cmp ch, cl ; IS IT THE SAME AS ASKED FOR TRACK 7054 00001C08 7407 <1> jz short NO_DBL ; IF SAME THEN NO DOUBLE STEP 7055 00001C0A 808F[F7670000]20 <1> or byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED 7056 <1> NO_DBL: 7057 00001C11 F8 <1> clc ; CLEAR ERROR FLAG 7058 00001C12 C3 <1> retn 7059 <1> 7060 <1> ;------------------------------------------------------------------------------- 7061 <1> ; READ_ID 7062 <1> ; READ ID FUNCTION. 7063 <1> ; 7064 <1> ; ON ENTRY: EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE 7065 <1> ; 7066 <1> ; ON EXIT: EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE 7067 <1> ; @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 7068 <1> ;------------------------------------------------------------------------------- 7069 <1> READ_ID: 7070 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7071 00001C13 B8[2F1C0000] <1> mov eax, ER_3 ; MOVE NEC OUTPUT ERROR ADDRESS 7072 00001C18 50 <1> push eax 7073 00001C19 B44A <1> mov ah, 4Ah ; READ ID COMMAND 7074 00001C1B E80A010000 <1> call NEC_OUTPUT ; TO CONTROLLER 7075 00001C20 89F8 <1> mov eax, edi ; DRIVE # TO AH, HEAD 0 7076 00001C22 88C4 <1> mov ah, al 7077 00001C24 E801010000 <1> call NEC_OUTPUT ; TO CONTROLLER 7078 00001C29 E839FEFFFF <1> call NEC_TERM ; WAIT FOR OPERATION, GET STATUS 7079 00001C2E 58 <1> pop eax ; THROW AWAY ERROR ADDRESS 7080 <1> ER_3: 7081 00001C2F C3 <1> retn 7082 <1> 7083 <1> ;------------------------------------------------------------------------------- 7084 <1> ; CMOS_TYPE 7085 <1> ; RETURNS CMOS DISKETTE TYPE 7086 <1> ; 7087 <1> ; ON ENTRY: EDI = DRIVE # 7088 <1> ; 7089 <1> ; ON EXIT: AL = TYPE; CY REFLECTS STATUS 7090 <1> ;------------------------------------------------------------------------------- 7091 <1> 7092 <1> CMOS_TYPE: ; 11/12/2014 7093 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7094 00001C30 8A87[8C620000] <1> mov al, [edi+fd0_type] ; diskette type 7095 00001C36 20C0 <1> and al, al ; 18/12/2014 7096 00001C38 C3 <1> retn 7097 <1> 7098 <1> ;------------------------------------------------------------------------------- 7099 <1> ; GET_PARM 7100 <1> ; THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE 7101 <1> ; BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM 7102 <1> ; THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING 7103 <1> ; THE PARAMETER IN DL. 7104 <1> ; 7105 <1> ; ON ENTRY: AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022 7106 <1> ; 7107 <1> ; ON EXIT: AH = THAT BYTE FROM BLOCK 7108 <1> ; AL DESTROYED 7109 <1> ;------------------------------------------------------------------------------- 7110 <1> GET_PARM: 7111 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7112 <1> ; ENTRY: 7113 <1> ; AL = INDEX 7114 <1> ; EDI = DRIVE # 7115 <1> ; RETURN: 7116 <1> ; AH = REQUESTED PARAMETER 7117 <1> ; AL DESTROYED 7118 <1> 7119 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7120 <1> ; 08/02/2015 (protected mode modifications, bx -> ebx) 7121 <1> ;push esi ; 11/07/2022 7122 00001C39 53 <1> push ebx ; SAVE EBX 7123 00001C3A 0FB6D8 <1> movzx ebx, al ; EBX = INDEX 7124 <1> ; 17/12/2014 7125 <1> ;mov ax, [cfd] ; current (AL) and previous fd (AH) 7126 <1> ; 11/07/2022 7127 <1> ;cmp al, ah 7128 <1> ;je short gpndc 7129 <1> 7130 <1> ; 11/07/2022 7131 00001C3D 89F8 <1> mov eax, edi 7132 00001C3F 3A05[81620000] <1> cmp al, [pfd] ; is same with previous drive # ? 7133 00001C45 7423 <1> je short gpndc 7134 <1> 7135 00001C47 A2[81620000] <1> mov [pfd], al ; current drive -> previous drive 7136 <1> 7137 00001C4C 53 <1> push ebx ; 08/02/2015 7138 <1> 7139 <1> ;mov bl, al 7140 <1> ; 11/12/2014 7141 <1> ;mov al, [ebx+fd0_type] ; Drive type (0,1,2,3,4) 7142 <1> ; 11/07/2022 7143 00001C4D 8A87[8C620000] <1> mov al, [edi+fd0_type] ; Drive type (0,1,2,3,4) 7144 <1> ; 18/12/2014 7145 00001C53 20C0 <1> and al, al 7146 00001C55 7507 <1> jnz short gpdtc 7147 00001C57 BB[6B620000] <1> mov ebx, MD_TBL6 ; 1.44 MB param. tbl. (default) 7148 00001C5C EB05 <1> jmp short gpdpu 7149 <1> gpdtc: 7150 00001C5E E8B0FBFFFF <1> call DR_TYPE_CHECK 7151 <1> ; cf = 1 -> EBX points to 1.44MB fd parameter table (default) 7152 <1> gpdpu: 7153 00001C63 891D[08620000] <1> mov [DISK_POINTER], ebx 7154 00001C69 5B <1> pop ebx 7155 <1> gpndc: 7156 <1> ;mov esi, [DISK_POINTER] ; 08/02/2015, si -> esi 7157 <1> ;mov ah, [esi+ebx] ; GET THE WORD 7158 <1> ; 11/07/2022 7159 00001C6A 031D[08620000] <1> add ebx, [DISK_POINTER] 7160 00001C70 8A23 <1> mov ah, [ebx] 7161 00001C72 5B <1> pop ebx ; RESTORE EBX 7162 <1> ;pop esi ; 11/07/2022 7163 00001C73 C3 <1> retn 7164 <1> 7165 <1> ;------------------------------------------------------------------------------- 7166 <1> ; MOTOR_ON 7167 <1> ; TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT 7168 <1> ; IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE 7169 <1> ; THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE 7170 <1> ; MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION 7171 <1> ; (AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM 7172 <1> ; THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS 7173 <1> ; FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT 7174 <1> ; HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE 7175 <1> ; THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID 7176 <1> ; NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE 7177 <1> ; PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN, 7178 <1> ; IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE 7179 <1> ; WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT. 7180 <1> ; 7181 <1> ; ON ENTRY: EDI = DRIVE # 7182 <1> ; ON EXIT: EAX, ECX, EDX DESTROYED 7183 <1> ;------------------------------------------------------------------------------- 7184 <1> MOTOR_ON: 7185 <1> ; 12/07/2022 7186 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7187 00001C74 53 <1> push ebx ; SAVE REG. 7188 00001C75 E820000000 <1> call TURN_ON ; TURN ON MOTOR 7189 00001C7A 721C <1> jc short MOT_IS_ON ; IF CY=1 NO WAIT 7190 <1> ;call XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 7191 <1> ; 08/07/2022 7192 <1> ;call XLAT_NEW ; 12/07/2022 ; TRANSLATE STATE TO PRESENT ARCH, 7193 <1> ;call TURN_ON ; CHECK AGAIN IF MOTOR ON 7194 <1> ;jc short MOT_IS_ON ; IF NO WAIT MEANS IT IS ON 7195 <1> M_WAIT: 7196 <1> ;mov dl,10 ; GET THE MOTOR WAIT PARAMETER 7197 00001C7C B00A <1> mov al, 10 ; 08/07/2022 7198 00001C7E E8B6FFFFFF <1> call GET_PARM 7199 <1> ; 08/07/2022 ; AH = MOTOR WAIT PARAMETER 7200 00001C83 80FC08 <1> cmp ah, 8 ; SEE IF AT LEAST A SECOND IS SPECIFIED 7201 <1> ;jae short GP2 ; IF YES, CONTINUE 7202 00001C86 7302 <1> jae short J13 7203 00001C88 B408 <1> mov ah, 8 ; ONE SECOND WAIT FOR MOTOR START UP 7204 <1> 7205 <1> ;----- AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT 7206 <1> GP2: 7207 <1> ;----- FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE 7208 <1> J13: ; WAIT FOR 1/8 SECOND PER (AL) 7209 00001C8A B95E200000 <1> mov ecx, 8286 ; COUNT FOR 1/8 SECOND AT 15.085737 US 7210 00001C8F E817F7FFFF <1> call WAITF ; GO TO FIXED WAIT ROUTINE 7211 <1> ;dec al ; DECREMENT TIME VALUE 7212 00001C94 FECC <1> dec ah 7213 00001C96 75F2 <1> jnz short J13 ; ARE WE DONE YET 7214 <1> MOT_IS_ON: 7215 00001C98 5B <1> pop ebx ; RESTORE REG. 7216 00001C99 C3 <1> retn 7217 <1> 7218 <1> ;------------------------------------------------------------------------------- 7219 <1> ; TURN_ON 7220 <1> ; TURN MOTOR ON AND RETURN WAIT STATE. 7221 <1> ; 7222 <1> ; ON ENTRY: EDI = DRIVE # 7223 <1> ; 7224 <1> ; ON EXIT: CY = 0 MEANS WAIT REQUIRED 7225 <1> ; CY = 1 MEANS NO WAIT REQUIRED 7226 <1> ; EAX, EBX, ECX, EDX DESTROYED 7227 <1> ;------------------------------------------------------------------------------- 7228 <1> TURN_ON: 7229 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7230 00001C9A 89FB <1> mov ebx, edi ; EBX = DRIVE # 7231 00001C9C 88D9 <1> mov cl, bl ; CL = DRIVE # 7232 00001C9E C0C304 <1> rol bl, 4 ; BL = DRIVE SELECT 7233 00001CA1 FA <1> cli ; NO INTERRUPTS WHILE DETERMINING STATUS 7234 00001CA2 C605[EB670000]FF <1> mov byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 7235 00001CA9 A0[EA670000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 7236 00001CAE 2430 <1> and al, 00110000b ; KEEP ONLY DRIVE SELECT BITS 7237 00001CB0 B401 <1> mov ah, 1 ; MASK FOR DETERMINING MOTOR BIT 7238 00001CB2 D2E4 <1> shl ah, cl ; AH = MOTOR ON, A=00000001, B=00000010 7239 <1> 7240 <1> ; AL = DRIVE SELECT FROM @MOTOR_STATUS 7241 <1> ; BL = DRIVE SELECT DESIRED 7242 <1> ; AH = MOTOR ON MASK DESIRED 7243 <1> 7244 00001CB4 38D8 <1> cmp al, bl ; REQUESTED DRIVE ALREADY SELECTED ? 7245 00001CB6 7508 <1> jne short TURN_IT_ON ; IF NOT SELECTED JUMP 7246 00001CB8 8425[EA670000] <1> test ah, [MOTOR_STATUS] ; TEST MOTOR ON BIT 7247 00001CBE 7535 <1> jnz short NO_MOT_WAIT ; JUMP IF MOTOR ON AND SELECTED 7248 <1> 7249 <1> TURN_IT_ON: 7250 00001CC0 08DC <1> or ah, bl ; AH = DRIVE SELECT AND MOTOR ON 7251 00001CC2 8A3D[EA670000] <1> mov bh, [MOTOR_STATUS] ; SAVE COPY OF @MOTOR_STATUS BEFORE 7252 00001CC8 80E70F <1> and bh, 00001111b ; KEEP ONLY MOTOR BITS 7253 00001CCB 8025[EA670000]CF <1> and byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT 7254 00001CD2 0825[EA670000] <1> or [MOTOR_STATUS], ah ; OR IN DRIVE SELECTED AND MOTOR ON 7255 00001CD8 A0[EA670000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 7256 00001CDD 88C3 <1> mov bl, al ; BL=@MOTOR_STATUS AFTER, BH=BEFORE 7257 00001CDF 80E30F <1> and bl, 00001111b ; KEEP ONLY MOTOR BITS 7258 00001CE2 FB <1> sti ; ENABLE INTERRUPTS AGAIN 7259 00001CE3 243F <1> and al, 00111111b ; STRIP AWAY UNWANTED BITS 7260 00001CE5 C0C004 <1> rol al, 4 ; PUT BITS IN DESIRED POSITIONS 7261 00001CE8 0C0C <1> or al, 00001100b ; NO RESET, ENABLE DMA/INTERRUPT 7262 00001CEA 66BAF203 <1> mov dx, 03F2h ; SELECT DRIVE AND TURN ON MOTOR 7263 00001CEE EE <1> out dx, al 7264 00001CEF 38FB <1> cmp bl, bh ; NEW MOTOR TURNED ON ? 7265 <1> ;je short NO_MOT_WAIT ; NO WAIT REQUIRED IF JUST SELECT 7266 00001CF1 7403 <1> je short no_mot_w1 ; 27/02/2015 7267 00001CF3 F8 <1> clc ; RESET CARRY MEANING WAIT 7268 00001CF4 C3 <1> retn 7269 <1> 7270 <1> NO_MOT_WAIT: 7271 00001CF5 FB <1> sti 7272 <1> no_mot_w1: ; 27/02/2015 7273 00001CF6 F9 <1> stc ; SET NO WAIT REQUIRED 7274 <1> ;sti ; INTERRUPTS BACK ON 7275 00001CF7 C3 <1> retn 7276 <1> 7277 <1> ;------------------------------------------------------------------------------- 7278 <1> ; HD_WAIT 7279 <1> ; WAIT FOR HEAD SETTLE TIME. 7280 <1> ; 7281 <1> ; ON ENTRY: DI = DRIVE # 7282 <1> ; 7283 <1> ; ON EXIT: AX,BX,CX,DX DESTROYED 7284 <1> ;------------------------------------------------------------------------------- 7285 <1> HD_WAIT: 7286 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7287 <1> ;mov dl, 9 ; GET HEAD SETTLE PARAMETER 7288 00001CF8 B009 <1> mov al, 9 ; 08/07/2022 7289 00001CFA E83AFFFFFF <1> CALL GET_PARM 7290 00001CFF 08E4 <1> or ah, ah ; 17/12/2014 ; CHECK FOR ANY WAIT? 7291 00001D01 7519 <1> jnz short DO_WAT ; IF THERE DO NOT ENFORCE 7292 00001D03 F605[EA670000]80 <1> test byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION 7293 <1> ;jz short ISNT_WRITE ; IF NOT, DO NOT ENFORCE ANY VALUES 7294 <1> ;or ah, ah ; CHECK FOR ANY WAIT? 7295 <1> ;jnz short DO_WAT ; IF THERE DO NOT ENFORCE 7296 00001D0A 741D <1> jz short HW_DONE 7297 00001D0C B40F <1> mov ah, HD12_SETTLE ; LOAD 1.2M HEAD SETTLE MINIMUM 7298 00001D0E 8A87[F7670000] <1> mov al, [DSK_STATE+edi] ; LOAD STATE 7299 00001D14 24C0 <1> and al, RATE_MSK ; KEEP ONLY RATE 7300 00001D16 3C80 <1> cmp al, RATE_250 ; 1.2 M DRIVE ? 7301 00001D18 7502 <1> jnz short DO_WAT ; DEFAULT HEAD SETTLE LOADED 7302 <1> ;GP3: 7303 00001D1A B414 <1> mov ah, HD320_SETTLE ; USE 320/360 HEAD SETTLE 7304 <1> ; jmp short DO_WAT 7305 <1> 7306 <1> ;ISNT_WRITE: 7307 <1> ; or ah, ah ; CHECK FOR NO WAIT 7308 <1> ; jz short HW_DONE ; IF NOT WRITE AND 0 ITS OK 7309 <1> 7310 <1> ;----- AH CONTAINS NUMBER OF MILLISECONDS TO WAIT 7311 <1> DO_WAT: 7312 <1> ; mov al, ah ; AL = # MILLISECONDS 7313 <1> ; ;xor ah, ah ; AX = # MILLISECONDS 7314 <1> J29: ; 1 MILLISECOND LOOP 7315 <1> ;mov cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units. 7316 <1> ;mov ecx, 66 ; COUNT AT 15.085737 US PER COUNT 7317 <1> ; 08/07/2022 7318 00001D1C 29C9 <1> sub ecx, ecx 7319 00001D1E B142 <1> mov cl, 66 7320 00001D20 E886F6FFFF <1> call WAITF ; DELAY FOR 1 MILLISECOND 7321 <1> ;dec al ; DECREMENT THE COUNT 7322 00001D25 FECC <1> dec ah 7323 00001D27 75F3 <1> jnz short J29 ; DO AL MILLISECOND # OF TIMES 7324 <1> HW_DONE: 7325 00001D29 C3 <1> retn 7326 <1> 7327 <1> ;------------------------------------------------------------------------------- 7328 <1> ; NEC_OUTPUT 7329 <1> ; THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING 7330 <1> ; FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL 7331 <1> ; TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT 7332 <1> ; OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION. 7333 <1> ; 7334 <1> ; ON ENTRY: AH = BYTE TO BE OUTPUT 7335 <1> ; 7336 <1> ; ON EXIT: CY = 0 SUCCESS 7337 <1> ; CY = 1 FAILURE -- DISKETTE STATUS UPDATED 7338 <1> ; IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL 7339 <1> ; HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE 7340 <1> ; REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT. 7341 <1> ; 7342 <1> ; EAX, ECX, EDX DESTROYED 7343 <1> ;------------------------------------------------------------------------------- 7344 <1> 7345 <1> ; 09/12/2014 [Erdogan Tan] 7346 <1> ; (from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.) 7347 <1> ; Diskette Drive Controller Status Register (3F4h) 7348 <1> ; This read only register facilitates the transfer of data between 7349 <1> ; the system microprocessor and the controller. 7350 <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 7351 <1> ; with the system micrprocessor. 7352 <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0, 7353 <1> ; the transfer is to the controller. 7354 <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode. 7355 <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed. 7356 <1> ; Bit 3 - Reserved. 7357 <1> ; Bit 2 - Reserved. 7358 <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode. 7359 <1> ; Bit 0 - When this bit is set to 1, dskette drive 0 is in the seek mode. 7360 <1> 7361 <1> ; Data Register (3F5h) 7362 <1> ; This read/write register passes data, commands and parameters, and provides 7363 <1> ; diskette status information. 7364 <1> 7365 <1> NEC_OUTPUT: 7366 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7367 <1> ;push ebx ; SAVE REG. 7368 00001D2A BAF4030000 <1> mov edx, 03F4h ; STATUS PORT 7369 <1> ;xor ecx, ecx ; COUNT FOR TIME OUT 7370 <1> ; 16/12/2014 7371 <1> ; waiting for (max.) 0.5 seconds 7372 <1> ;;mov byte [wait_count], 0 ;; 27/02/2015 7373 <1> ; 7374 <1> ; 17/12/2014 7375 <1> ; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND 7376 <1> ; 7377 <1> ;WAIT_FOR_PORT: Waits for a bit at a port pointed to by DX to 7378 <1> ; go on. 7379 <1> ;INPUT: 7380 <1> ; AH=Mask for isolation bits. 7381 <1> ; AL=pattern to look for. 7382 <1> ; DX=Port to test for 7383 <1> ; ECX=Number of memory refresh periods to delay. 7384 <1> ; (normally 30 microseconds per period.) 7385 <1> ; 7386 <1> ;WFP_SHORT: 7387 <1> ; Wait for port if refresh cycle is short (15-80 Us range). 7388 <1> ; 7389 <1> 7390 00001D2F B91B410000 <1> mov ecx, WAIT_FDU_SEND_LH ; 16667 (27/02/2015) 7391 <1> ; 7392 <1> ;WFPS_OUTER_LP: 7393 <1> ; ; 7394 <1> ;WFPS_CHECK_PORT: 7395 <1> J23: 7396 00001D34 EC <1> in al, dx ; GET STATUS 7397 00001D35 24C0 <1> and al, 11000000b ; KEEP STATUS AND DIRECTION 7398 00001D37 3C80 <1> cmp al, 10000000b ; STATUS 1 AND DIRECTION 0 ? 7399 00001D39 7418 <1> jz short J27 ; STATUS AND DIRECTION OK 7400 <1> WFPS_HI: 7401 00001D3B E461 <1> in al, PORT_B ; 061h ; SYS1 ; wait for hi to lo 7402 00001D3D A810 <1> test al, 010h ; transition on memory 7403 00001D3F 75FA <1> jnz short WFPS_HI ; refresh. 7404 <1> WFPS_LO: 7405 00001D41 E461 <1> in al, PORT_B ; SYS1 7406 00001D43 A810 <1> test al, 010h 7407 00001D45 74FA <1> jz short WFPS_LO 7408 <1> ;loop short WFPS_CHECK_PORT 7409 00001D47 E2EB <1> loop J23 ; 27/02/2015 ; REPEAT TILL DELAY FINISHED 7410 <1> 7411 <1> ; fail 7412 <1> 7413 <1> ;WFPS_TIMEOUT: 7414 <1> 7415 <1> ;----- FALL THRU TO ERROR RETURN 7416 <1> 7417 00001D49 800D[EC670000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT 7418 <1> ;pop ebx ; RESTORE REG. 7419 00001D50 58 <1> pop eax ; 08/02/2015 ; DISCARD THE RETURN ADDRESS 7420 00001D51 F9 <1> stc ; INDICATE ERROR TO CALLER 7421 00001D52 C3 <1> retn 7422 <1> 7423 <1> ;----- DIRECTION AND STATUS OK; OUTPUT BYTE 7424 <1> 7425 <1> J27: 7426 00001D53 88E0 <1> mov al, ah ; GET BYTE TO OUTPUT 7427 00001D55 42 <1> inc edx ; DATA PORT = STATUS PORT + 1 7428 00001D56 EE <1> out dx, al ; OUTPUT THE BYTE 7429 <1> ;;NEWIODELAY ;; 27/02/2015 7430 <1> ; 27/02/2015 7431 00001D57 9C <1> pushfd ; 24/12/2021 ; SAVE FLAGS 7432 <1> ;mov ecx, 3 ; 30 TO 45 MICROSECONDS WAIT FOR 7433 00001D58 29C9 <1> sub ecx, ecx 7434 00001D5A B103 <1> mov cl, 3 ; 24/12/2021 7435 00001D5C E84AF6FFFF <1> call WAITF ; NEC FLAGS UPDATE CYCLE 7436 00001D61 9D <1> popfd ; 24/12/2021 ; RESTORE FLAGS FOR EXIT 7437 <1> ;pop ebx ; RESTORE REG 7438 00001D62 C3 <1> retn ; CY = 0 FROM TEST INSTRUCTION 7439 <1> 7440 <1> ;------------------------------------------------------------------------------- 7441 <1> ; SEEK 7442 <1> ; THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED 7443 <1> ; TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE 7444 <1> ; RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED. 7445 <1> ; 7446 <1> ; ON ENTRY: EDI = DRIVE # 7447 <1> ; CH = TRACK # 7448 <1> ; 7449 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7450 <1> ; EAX, EBX, ECX, EDX DESTROYED 7451 <1> ;------------------------------------------------------------------------------- 7452 <1> SEEK: 7453 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7454 00001D63 89FB <1> mov ebx, edi ; EBX = DRIVE # 7455 00001D65 B001 <1> mov al, 1 ; ESTABLISH MASK FOR RECALIBRATE TEST 7456 00001D67 86CB <1> xchg cl, bl ; SET DRIVE VALUE INTO CL 7457 00001D69 D2C0 <1> rol al, cl ; SHIFT MASK BY THE DRIVE VALUE 7458 00001D6B 86CB <1> xchg cl, bl ; RECOVER DRIVE VALUE 7459 00001D6D 8405[E9670000] <1> test al, [SEEK_STATUS] ; TEST FOR RECALIBRATE REQUIRED 7460 00001D73 7526 <1> jnz short J28A ; JUMP IF RECALIBRATE NOT REQUIRED 7461 <1> 7462 00001D75 0805[E9670000] <1> or [SEEK_STATUS], al ; TURN ON THE NO RECALIBRATE BIT IN FLAG 7463 00001D7B E862000000 <1> call RECAL ; RECALIBRATE DRIVE 7464 00001D80 730E <1> jnc short AFT_RECAL ; RECALIBRATE DONE 7465 <1> 7466 <1> ;----- ISSUE RECALIBRATE FOR 80 TRACK DISKETTES 7467 <1> 7468 00001D82 C605[EC670000]00 <1> mov byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS 7469 00001D89 E854000000 <1> call RECAL ; RECALIBRATE DRIVE 7470 00001D8E 7251 <1> jc short RB ; IF RECALIBRATE FAILS TWICE THEN ERROR 7471 <1> 7472 <1> AFT_RECAL: 7473 00001D90 C687[F9670000]00 <1> mov byte [DSK_TRK+edi], 0 ; SAVE NEW CYLINDER AS PRESENT POSITION 7474 00001D97 08ED <1> or ch, ch ; CHECK FOR SEEK TO TRACK 0 7475 00001D99 743F <1> jz short DO_WAIT ; HEAD SETTLE, CY = 0 IF JUMP 7476 <1> 7477 <1> ;----- DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK 7478 <1> 7479 00001D9B F687[F7670000]20 <1> J28A: test byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED 7480 00001DA2 7402 <1> jz short _R7 ; SINGLE STEP REQUIRED BYPASS DOUBLE 7481 00001DA4 D0E5 <1> shl ch, 1 ; DOUBLE NUMBER OF STEP TO TAKE 7482 <1> 7483 00001DA6 3AAF[F9670000] <1> _R7: cmp ch, [DSK_TRK+edi] ; SEE IF ALREADY AT THE DESIRED TRACK 7484 00001DAC 7433 <1> je short RB ; IF YES, DO NOT NEED TO SEEK 7485 <1> 7486 00001DAE BA[E11D0000] <1> mov edx, NEC_ERR ; LOAD RETURN ADDRESS 7487 00001DB3 52 <1> push edx ; (*) ; ON STACK FOR NEC OUTPUT ERROR 7488 00001DB4 88AF[F9670000] <1> mov [DSK_TRK+edi], ch ; SAVE NEW CYLINDER AS PRESENT POSITION 7489 00001DBA B40F <1> mov ah, 0Fh ; SEEK COMMAND TO NEC 7490 00001DBC E869FFFFFF <1> call NEC_OUTPUT 7491 00001DC1 89FB <1> mov ebx, edi ; EBX = DRIVE # 7492 00001DC3 88DC <1> mov ah, bl ; OUTPUT DRIVE NUMBER 7493 00001DC5 E860FFFFFF <1> call NEC_OUTPUT 7494 00001DCA 8AA7[F9670000] <1> mov ah, [DSK_TRK+edi] ; GET CYLINDER NUMBER 7495 00001DD0 E855FFFFFF <1> call NEC_OUTPUT 7496 00001DD5 E827000000 <1> call CHK_STAT_2 ; ENDING INTERRUPT AND SENSE STATUS 7497 <1> 7498 <1> ;----- WAIT FOR HEAD SETTLE 7499 <1> 7500 <1> DO_WAIT: 7501 00001DDA 9C <1> pushfd ; 24/12/2021 ; SAVE STATUS 7502 00001DDB E818FFFFFF <1> call HD_WAIT ; WAIT FOR HEAD SETTLE TIME 7503 00001DE0 9D <1> popfd ; 24/12/2021 ; RESTORE STATUS 7504 <1> RB: 7505 <1> NEC_ERR: 7506 <1> ; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM) 7507 <1> ; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn 7508 00001DE1 C3 <1> retn ; RETURN TO CALLER 7509 <1> 7510 <1> ;------------------------------------------------------------------------------- 7511 <1> ; RECAL 7512 <1> ; RECALIBRATE DRIVE 7513 <1> ; 7514 <1> ; ON ENTRY: EDI = DRIVE # 7515 <1> ; 7516 <1> ; ON EXIT: CY REFLECTS STATUS OF OPERATION. 7517 <1> ;------------------------------------------------------------------------------- 7518 <1> RECAL: 7519 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7520 <1> ;push cx 7521 <1> ; 24/12/2021 7522 00001DE2 51 <1> push ecx 7523 00001DE3 B8[FF1D0000] <1> mov eax, RC_BACK ; LOAD NEC_OUTPUT ERROR 7524 00001DE8 50 <1> push eax 7525 00001DE9 B407 <1> mov ah, 07h ; RECALIBRATE COMMAND 7526 00001DEB E83AFFFFFF <1> call NEC_OUTPUT 7527 00001DF0 89FB <1> mov ebx, edi ; EBX = DRIVE # 7528 00001DF2 88DC <1> mov ah, bl 7529 00001DF4 E831FFFFFF <1> call NEC_OUTPUT ; OUTPUT THE DRIVE NUMBER 7530 00001DF9 E803000000 <1> call CHK_STAT_2 ; GET THE INTERRUPT AND SENSE INT STATUS 7531 00001DFE 58 <1> pop eax ; THROW AWAY ERROR 7532 <1> RC_BACK: 7533 <1> ;pop cx 7534 <1> ; 24/12/2021 7535 00001DFF 59 <1> pop ecx 7536 00001E00 C3 <1> RETn 7537 <1> 7538 <1> ;------------------------------------------------------------------------------- 7539 <1> ; CHK_STAT_2 7540 <1> ; THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE, 7541 <1> ; OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE 7542 <1> ; INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER. 7543 <1> ; 7544 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7545 <1> ;------------------------------------------------------------------------------- 7546 <1> CHK_STAT_2: 7547 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7548 00001E01 B8[291E0000] <1> mov eax, CS_BACK ; LOAD NEC_OUTPUT ERROR ADDRESS 7549 00001E06 50 <1> push eax 7550 00001E07 E828000000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 7551 00001E0C 721A <1> jc short J34 ; IF ERROR, RETURN IT 7552 00001E0E B408 <1> mov ah, 08h ; SENSE INTERRUPT STATUS COMMAND 7553 00001E10 E815FFFFFF <1> call NEC_OUTPUT 7554 00001E15 E849000000 <1> call RESULTS ; READ IN THE RESULTS 7555 00001E1A 720C <1> jc short J34 7556 00001E1C A0[ED670000] <1> mov al, [NEC_STATUS] ; GET THE FIRST STATUS BYTE 7557 00001E21 2460 <1> and al, 01100000b ; ISOLATE THE BITS 7558 00001E23 3C60 <1> cmp al, 01100000b ; TEST FOR CORRECT VALUE 7559 00001E25 7403 <1> jz short J35 ; IF ERROR, GO MARK IT 7560 00001E27 F8 <1> clc ; GOOD RETURN 7561 <1> J34: 7562 00001E28 58 <1> pop eax ; THROW AWAY ERROR RETURN 7563 <1> CS_BACK: 7564 00001E29 C3 <1> retn 7565 <1> J35: 7566 00001E2A 800D[EC670000]40 <1> or byte [DSKETTE_STATUS], BAD_SEEK 7567 00001E31 F9 <1> stc ; ERROR RETURN CODE 7568 00001E32 EBF4 <1> jmp short J34 7569 <1> 7570 <1> ;------------------------------------------------------------------------------- 7571 <1> ; WAIT_INT 7572 <1> ; THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE 7573 <1> ; TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED 7574 <1> ; IF THE DRIVE IS NOT READY. 7575 <1> ; 7576 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7577 <1> ;------------------------------------------------------------------------------- 7578 <1> 7579 <1> ; 17/12/2014 7580 <1> ; 2.5 seconds waiting ! 7581 <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI) 7582 <1> ; amount of time to wait for completion interrupt from NEC. 7583 <1> 7584 <1> WAIT_INT: 7585 <1> ; 12/07/2022 7586 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7587 00001E34 FB <1> sti ; TURN ON INTERRUPTS, JUST IN CASE 7588 <1> ; 12/07/2022 7589 <1> ;clc ; CLEAR TIMEOUT INDICATOR 7590 <1> ;mov bl, 10 ; CLEAR THE COUNTERS 7591 <1> ;xor cx, cx ; FOR 2 SECOND WAIT 7592 <1> 7593 <1> ; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT 7594 <1> ; 7595 <1> ;WAIT_FOR_MEM: 7596 <1> ; Waits for a bit at a specified memory location pointed 7597 <1> ; to by ES:[DI] to become set. 7598 <1> ;INPUT: 7599 <1> ; AH=Mask to test with. 7600 <1> ; ES:[DI] = memory location to watch. 7601 <1> ; BH:CX=Number of memory refresh periods to delay. 7602 <1> ; (normally 30 microseconds per period.) 7603 <1> 7604 <1> ; waiting for (max.) 2.5 secs in 30 micro units. 7605 <1> ; mov cx, WAIT_FDU_INT_LO ; 017798 7606 <1> ;; mov bl, WAIT_FDU_INT_HI 7607 <1> ; mov bl, WAIT_FDU_INT_HI + 1 7608 <1> ; 27/02/2015 7609 00001E35 B986450100 <1> mov ecx, WAIT_FDU_INT_LH ; 83334 (2.5 seconds) 7610 <1> WFMS_CHECK_MEM: 7611 00001E3A F605[E9670000]80 <1> test byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING 7612 00001E41 7516 <1> jnz short J37 7613 <1> WFMS_HI: 7614 00001E43 E461 <1> in al, PORT_B ; 061h ; SYS1, wait for lo to hi 7615 00001E45 A810 <1> test al, 010h ; transition on memory 7616 00001E47 75FA <1> jnz short WFMS_HI ; refresh. 7617 <1> WFMS_LO: 7618 00001E49 E461 <1> in al, PORT_B ; SYS1 7619 00001E4B A810 <1> test al, 010h 7620 00001E4D 74FA <1> jz short WFMS_LO 7621 00001E4F E2E9 <1> loop WFMS_CHECK_MEM 7622 <1> ;WFMS_OUTER_LP: 7623 <1> ;; or bl, bl ; check outer counter 7624 <1> ;; jz short J36A ; WFMS_TIMEOUT 7625 <1> ; dec bl 7626 <1> ; jz short J36A 7627 <1> ; jmp short WFMS_CHECK_MEM 7628 <1> 7629 <1> ;17/12/2014 7630 <1> ;16/12/2014 7631 <1> ; mov byte [wait_count], 0 ; Reset (INT 08H) counter 7632 <1> ;J36: 7633 <1> ; test byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING 7634 <1> ; jnz short J37 7635 <1> ;16/12/2014 7636 <1> ;loop J36 ; COUNT DOWN WHILE WAITING 7637 <1> ;dec bl ; SECOND LEVEL COUNTER 7638 <1> ;jnz short J36 7639 <1> ; cmp byte [wait_count], 46 ; (46/18.2 seconds) 7640 <1> ; jb short J36 7641 <1> 7642 <1> ;WFMS_TIMEOUT: 7643 <1> ;J36A: 7644 00001E51 800D[EC670000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED 7645 00001E58 F9 <1> stc ; ERROR RETURN 7646 <1> J37: 7647 00001E59 9C <1> pushf ; SAVE CURRENT CARRY 7648 00001E5A 8025[E9670000]7F <1> and byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG 7649 00001E61 9D <1> popf ; RECOVER CARRY 7650 00001E62 C3 <1> retn ; GOOD RETURN CODE 7651 <1> 7652 <1> ;------------------------------------------------------------------------------- 7653 <1> ; RESULTS 7654 <1> ; THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 7655 <1> ; FOLLOWING AN INTERRUPT. 7656 <1> ; 7657 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7658 <1> ; EAX, EBX, ECX, EDX DESTROYED 7659 <1> ;------------------------------------------------------------------------------- 7660 <1> RESULTS: 7661 <1> ; 12/07/2022 7662 <1> ; 11/07/2022 7663 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7664 00001E63 57 <1> push edi 7665 00001E64 BF[ED670000] <1> mov edi, NEC_STATUS ; POINTER TO DATA AREA 7666 00001E69 B307 <1> mov bl, 7 ; MAX STATUS BYTES 7667 00001E6B 66BAF403 <1> mov dx, 03F4h ; STATUS PORT 7668 <1> 7669 <1> ;----- WAIT FOR REQUEST FOR MASTER 7670 <1> 7671 <1> _R10: 7672 <1> ; 16/12/2014 7673 <1> ; wait for (max) 0.5 seconds 7674 <1> ;mov bh, 2 ; HIGH ORDER COUNTER 7675 <1> ;xor cx, cx ; COUNTER 7676 <1> 7677 <1> ;Time to wait while waiting for each byte of NEC results = .5 7678 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 7679 <1> ; 27/02/2015 7680 <1> 7681 00001E6F B91B410000 <1> mov ecx, WAIT_FDU_RESULTS_LH ; 16667 7682 <1> ;mov cx, WAIT_FDU_RESULTS_LO ; 16667 7683 <1> ;mov bh, WAIT_FDU_RESULTS_HI+1 ; 0+1 7684 <1> 7685 <1> WFPSR_OUTER_LP: 7686 <1> ; 7687 <1> WFPSR_CHECK_PORT: 7688 <1> J39: ; WAIT FOR MASTER 7689 00001E74 EC <1> in al, dx ; GET STATUS 7690 00001E75 24C0 <1> and al, 11000000b ; KEEP ONLY STATUS AND DIRECTION 7691 00001E77 3CC0 <1> cmp al, 11000000b ; STATUS 1 AND DIRECTION 1 ? 7692 00001E79 7418 <1> jz short J42 ; STATUS AND DIRECTION OK 7693 <1> WFPSR_HI: 7694 00001E7B E461 <1> in al, PORT_B ;061h ; SYS1 ; wait for hi to lo 7695 00001E7D A810 <1> test al, 010h ; transition on memory 7696 00001E7F 75FA <1> jnz short WFPSR_HI ; refresh. 7697 <1> WFPSR_LO: 7698 00001E81 E461 <1> in al, PORT_B ; SYS1 7699 00001E83 A810 <1> test al, 010h 7700 00001E85 74FA <1> jz short WFPSR_LO 7701 00001E87 E2EB <1> loop WFPSR_CHECK_PORT 7702 <1> 7703 <1> ;; 27/02/2015 7704 <1> ;;dec bh 7705 <1> ;;jnz short WFPSR_OUTER_LP 7706 <1> ;jmp short WFPSR_TIMEOUT ; fail 7707 <1> 7708 <1> ;;mov byte [wait_count], 0 7709 <1> ;J39: ; WAIT FOR MASTER 7710 <1> ; in al, dx ; GET STATUS 7711 <1> ; and al, 11000000b ; KEEP ONLY STATUS AND DIRECTION 7712 <1> ; cmp al, 11000000b ; STATUS 1 AND DIRECTION 1 ? 7713 <1> ; jz short J42 ; STATUS AND DIRECTION OK 7714 <1> ;loop J39 ; LOOP TILL TIMEOUT 7715 <1> ;dec bh ; DECREMENT HIGH ORDER COUNTER 7716 <1> ;jnz short J39 ; REPEAT TILL DELAY DONE 7717 <1> ; 7718 <1> ;;cmp byte [wait_count], 10 ; (10/18.2 seconds) 7719 <1> ;;jb short J39 7720 <1> 7721 <1> ;WFPSR_TIMEOUT: 7722 00001E89 800D[EC670000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT 7723 00001E90 F9 <1> stc ; SET ERROR RETURN 7724 00001E91 EB26 <1> jmp short POPRES ; POP REGISTERS AND RETURN 7725 <1> 7726 <1> ;----- READ IN THE STATUS 7727 <1> 7728 <1> J42: 7729 00001E93 EB00 <1> JMP $+2 ; I/O DELAY 7730 <1> ;inc dx ; POINT AT DATA PORT 7731 00001E95 FEC2 <1> inc dl 7732 00001E97 EC <1> in al, dx ; GET THE DATA 7733 <1> ; 16/12/2014 7734 <1> NEWIODELAY 7735 00001E98 E6EB <2> out 0EBh,al 7736 <1> 7737 <1> ;mov [edi], al ; STORE THE BYTE 7738 <1> ;inc edi ; INCREMENT THE POINTER 7739 <1> ; 11/07/2022 7740 00001E9A AA <1> stosb 7741 <1> 7742 <1> ; 16/12/2014 7743 <1> ; push cx 7744 <1> ; mov cx, 30 7745 <1> ;wdw2: 7746 <1> ; NEWIODELAY 7747 <1> ; loop wdw2 7748 <1> ; pop cx 7749 <1> 7750 <1> ;mov ecx,3 ; MINIMUM 24 MICROSECONDS FOR NEC 7751 <1> ; 12/07/2022 7752 00001E9B 29C9 <1> sub ecx, ecx 7753 00001E9D B103 <1> mov cl, 3 7754 00001E9F E807F5FFFF <1> call WAITF ; WAIT 30 TO 45 MICROSECONDS 7755 <1> ;dec dx ; POINT AT STATUS PORT 7756 00001EA4 FECA <1> dec dl 7757 00001EA6 EC <1> in al, dx ; GET STATUS 7758 <1> ; 16/12/2014 7759 <1> NEWIODELAY 7760 00001EA7 E6EB <2> out 0EBh,al 7761 <1> ; 7762 00001EA9 A810 <1> test al, 00010000b ; TEST FOR NEC STILL BUSY 7763 00001EAB 740C <1> jz short POPRES ; RESULTS DONE ? 7764 <1> 7765 00001EAD FECB <1> dec bl ; DECREMENT THE STATUS COUNTER 7766 00001EAF 75BE <1> jnz short _R10 ; GO BACK FOR MORE 7767 00001EB1 800D[EC670000]20 <1> or byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES 7768 00001EB8 F9 <1> stc ; SET ERROR FLAG 7769 <1> 7770 <1> ;----- RESULT OPERATION IS DONE 7771 <1> POPRES: 7772 00001EB9 5F <1> pop edi 7773 00001EBA C3 <1> retn ; RETURN WITH CARRY SET 7774 <1> 7775 <1> ;------------------------------------------------------------------------------- 7776 <1> ; READ_DSKCHNG 7777 <1> ; READS THE STATE OF THE DISK CHANGE LINE. 7778 <1> ; 7779 <1> ; ON ENTRY: EDI = DRIVE # 7780 <1> ; 7781 <1> ; ON EXIT: EDI = DRIVE # 7782 <1> ; ZF = 0 : DISK CHANGE LINE INACTIVE 7783 <1> ; ZF = 1 : DISK CHANGE LINE ACTIVE 7784 <1> ; EAX, ECX, EDX DESTROYED 7785 <1> ;------------------------------------------------------------------------------- 7786 <1> READ_DSKCHNG: 7787 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7788 00001EBB E8B4FDFFFF <1> call MOTOR_ON ; TURN ON THE MOTOR IF OFF 7789 00001EC0 66BAF703 <1> mov dx, 03F7h ; ADDRESS DIGITAL INPUT REGISTER 7790 00001EC4 EC <1> in al, dx ; INPUT DIGITAL INPUT REGISTER 7791 00001EC5 A880 <1> test al, DSK_CHG ; CHECK FOR DISK CHANGE LINE ACTIVE 7792 00001EC7 C3 <1> retn ; RETURN TO CALLER WITH ZERO FLAG SET 7793 <1> 7794 <1> fdc_int: 7795 <1> ; 30/07/2015 7796 <1> ; 16/02/2015 7797 <1> ;int_0Eh: ; 11/12/2014 7798 <1> 7799 <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL 6 ) --------------------------------------- 7800 <1> ; DISK_INT 7801 <1> ; THIS ROUTINE HANDLES THE DISKETTE INTERRUPT. 7802 <1> ; 7803 <1> ; ON EXIT: THE INTERRUPT FLAG IS SET IN @SEEK_STATUS. 7804 <1> ;------------------------------------------------------------------------------- 7805 <1> DISK_INT_1: 7806 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7807 <1> ;push eax ; SAVE WORK REGISTER 7808 <1> ; 24/12/2021 7809 00001EC8 50 <1> push eax 7810 00001EC9 1E <1> push ds 7811 00001ECA 66B81000 <1> mov ax, KDATA 7812 00001ECE 8ED8 <1> mov ds, ax 7813 00001ED0 800D[E9670000]80 <1> or byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED 7814 00001ED7 B020 <1> mov al, EOI ; END OF INTERRUPT MARKER 7815 00001ED9 E620 <1> out INTA00, al ; INTERRUPT CONTROL PORT 7816 00001EDB 1F <1> pop ds 7817 <1> ;pop ax ; RECOVER REGISTER 7818 <1> ; 24/12/2021 7819 00001EDC 58 <1> pop eax 7820 00001EDD CF <1> iretd ; RETURN FROM INTERRUPT 7821 <1> 7822 <1> ;------------------------------------------------------------------------------- 7823 <1> ; DSKETTE_SETUP 7824 <1> ; THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF 7825 <1> ; DISKETTE DRIVES ARE ATTACH TO THE SYSTEM. 7826 <1> ;------------------------------------------------------------------------------- 7827 <1> DSKETTE_SETUP: 7828 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7829 <1> ;push eax ; SAVE REGISTERS 7830 <1> ;push ebx 7831 <1> ;push ecx 7832 00001EDE 52 <1> push edx 7833 <1> ;push edi 7834 <1> ; 14/12/2014 7835 <1> ;mov dword [DISK_POINTER], MD_TBL6 7836 <1> ; 7837 <1> ;or byte [RTC_WAIT_FLAG], 1 ; NO RTC WAIT, FORCE USE OF LOOP 7838 <1> 7839 00001EDF 31FF <1> xor edi, edi ; INITIALIZE DRIVE POINTER 7840 00001EE1 29C9 <1> sub ecx, ecx 7841 00001EE3 66890D[F7670000] <1> mov [DSK_STATE], cx ; 0 ; INITIALIZE STATES 7842 <1> ; 08/07/2022 7843 <1> ;and byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND 7844 00001EEA 800D[F4670000]C0 <1> or byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE 7845 00001EF1 880D[E9670000] <1> mov [SEEK_STATUS], cl ; 0 ; INDICATE RECALIBRATE NEEDED 7846 00001EF7 880D[EB670000] <1> mov [MOTOR_COUNT], cl ; 0 ; INITIALIZE MOTOR COUNT 7847 00001EFD 880D[EA670000] <1> mov [MOTOR_STATUS], cl ; 0 ; INITIALIZE DRIVES TO OFF STATE 7848 00001F03 880D[EC670000] <1> mov [DSKETTE_STATUS], cl ; 0 ; NO ERRORS 7849 <1> ; 7850 <1> ; 28/02/2015 7851 <1> ;mov word [cfd], 100h 7852 00001F09 E894F8FFFF <1> call DSK_RESET 7853 00001F0E 5A <1> pop edx 7854 00001F0F C3 <1> retn 7855 <1> 7856 <1> ;////////////////////////////////////////////////////// 7857 <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7858 <1> ; 7859 <1> 7860 <1> ; 12/07/2022 7861 <1> ;int13h: ; 21/02/2015 7862 <1> ; pushfd 7863 <1> ; push cs 7864 <1> ; call DISK_IO 7865 <1> ; retn 7866 <1> 7867 <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;; 7868 <1> ;///////////////////////////////////////////////////////////////////// 7869 <1> 7870 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7871 <1> ; ((Direct call instead of int 13h simulation)) 7872 <1> ; 7873 <1> ; Function in AL 7874 <1> ; 0 = reset 7875 <1> ; 1 = read 7876 <1> ; 2 = write 7877 <1> ; Disk drive number in DL 7878 <1> ; 0 & 1 = floppy disks 7879 <1> ; 80h .. 83h = hard disks 7880 <1> ; Sector address (LBA) in ECX 7881 <1> ; Buffer address in EBX 7882 <1> ; R/W sector count is (always) 1 7883 <1> ; 7884 <1> ; Return: 7885 <1> ; Status in AH (>0 = error code) 7886 <1> ; if CF = 1 -> error code in AH 7887 <1> ; if CF = 0 -> successful 7888 <1> ; AL = undefined 7889 <1> ; 7890 <1> ; Modified registers: (only) EAX 7891 <1> 7892 <1> ; 10/07/2022 7893 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7894 <1> 7895 <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project) 7896 <1> ; 23/02/2015 7897 <1> ; 21/02/2015 (unix386.s) 7898 <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s) 7899 <1> ; 7900 <1> ; Original Source Code: 7901 <1> ; DISK ----- 09/25/85 FIXED DISK BIOS 7902 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 7903 <1> ; 7904 <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 7905 <1> ; Source Code - ATORGS.ASM, AHDSK.ASM 7906 <1> ; 7907 <1> 7908 <1> ;The wait for controller to be not busy is 10 seconds. 7909 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 7910 <1> ;;WAIT_HDU_CTLR_BUSY_LO equ 1615h 7911 <1> ;;WAIT_HDU_CTLR_BUSY_HI equ 05h 7912 <1> WAIT_HDU_CTRL_BUSY_LH equ 51615h ;21/02/2015 7913 <1> 7914 <1> ;The wait for controller to issue completion interrupt is 10 seconds. 7915 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 7916 <1> ;;WAIT_HDU_INT_LO equ 1615h 7917 <1> ;;WAIT_HDU_INT_HI equ 05h 7918 <1> WAIT_HDU_INT_LH equ 51615h ; 21/02/2015 7919 <1> 7920 <1> ;The wait for Data request on read and write longs is 7921 <1> ;2000 us. (?) 7922 <1> ;;WAIT_HDU_DRQ_LO equ 1000 ; 03E8h 7923 <1> ;;WAIT_HDU_DRQ_HI equ 0 7924 <1> WAIT_HDU_DRQ_LH equ 1000 ; 21/02/2015 7925 <1> 7926 <1> ; Port 61h (PORT_B) 7927 <1> SYS1 equ 61h ; PORT_B (diskette.inc) 7928 <1> 7929 <1> ; 23/12/2014 7930 <1> %define CMD_BLOCK ebp-8 ; 21/02/2015 7931 <1> 7932 <1> ; 11/07/2022 7933 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 7934 <1> 7935 <1> ;--- INT 13H ------------------------------------------------------------------- 7936 <1> ; : 7937 <1> ; FIXED DISK I/O INTERFACE : 7938 <1> ; : 7939 <1> ; THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH : 7940 <1> ; THE IBM FIXED DISK CONTROLLER. : 7941 <1> ; : 7942 <1> ; THE BIOS ROUTINES ARE MEANT TO BE ACCESSED THROUGH : 7943 <1> ; SOFTWARE INTERRUPTS ONLY. ANY ADDRESSES PRESENT IN : 7944 <1> ; THESE LISTINGS ARE INCLUDED ONLY FOR COMPLETENESS, : 7945 <1> ; NOT FOR REFERENCE. APPLICATIONS WHICH REFERENCE ANY : 7946 <1> ; ABSOLUTE ADDRESSES WITHIN THE CODE SEGMENTS OF BIOS : 7947 <1> ; VIOLATE THE STRUCTURE AND DESIGN OF BIOS. : 7948 <1> ; : 7949 <1> ;------------------------------------------------------------------------------: 7950 <1> ; : 7951 <1> ; INPUT (AH)= HEX COMMAND VALUE : 7952 <1> ; : 7953 <1> ; (AH)= 00H RESET DISK (DL = 80H,81H) / DISKETTE : 7954 <1> ; (AH)= 01H READ THE DESIRED SECTORS INTO MEMORY : 7955 <1> ; (AH)= 02H WRITE THE DESIRED SECTORS FROM MEMORY : 7956 <1> ; : 7957 <1> ;------------------------------------------------------------------------------: 7958 <1> ; : 7959 <1> ; REGISTERS USED FOR FIXED DISK OPERATIONS : 7960 <1> ; : 7961 <1> ; (DL) - DRIVE NUMBER (80H-81H FOR DISK. VALUE CHECKED) : 7962 <1> ; (DH) - HEAD NUMBER (0-15 ALLOWED, NOT VALUE CHECKED) : 7963 <1> ; (CH) - CYLINDER NUMBER (0-1023, NOT VALUE CHECKED)(SEE CL): 7964 <1> ; (CL) - SECTOR NUMBER (1-17, NOT VALUE CHECKED) : 7965 <1> ; : 7966 <1> ; NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED : 7967 <1> ; IN THE HIGH 2 BITS OF THE CL REGISTER : 7968 <1> ; (10 BITS TOTAL) : 7969 <1> ; : 7970 <1> ; (AL) - NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H, : 7971 <1> ; FOR READ/WRITE LONG 1-79H) : 7972 <1> ; : 7973 <1> ; (EBX) - ADDRESS OF BUFFER FOR READS AND WRITES, : 7974 <1> ; (NOT REQUIRED FOR VERIFY) : 7975 <1> ; : 7976 <1> ;------------------------------------------------------------------------------: 7977 <1> ; OUTPUT : 7978 <1> ; AH = STATUS OF CURRENT OPERATION : 7979 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES BELOW : 7980 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) : 7981 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) : 7982 <1> ; : 7983 <1> ; NOTE: ERROR 11H INDICATES THAT THE DATA READ HAD A RECOVERABLE : 7984 <1> ; ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM. THE DATA : 7985 <1> ; IS PROBABLY GOOD, HOWEVER THE BIOS ROUTINE INDICATES AN : 7986 <1> ; ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE : 7987 <1> ; FOR ITSELF. THE ERROR MAY NOT RECUR IF THE DATA IS : 7988 <1> ; REWRITTEN. : 7989 <1> ; : 7990 <1> ; IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), : 7991 <1> ; INPUT: : 7992 <1> ; (DL) = DRIVE NUMBER : 7993 <1> ; OUTPUT: : 7994 <1> ; (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2) : 7995 <1> ; (CONTROLLER CARD ZERO TALLY ONLY) : 7996 <1> ; (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER : 7997 <1> ; (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER : 7998 <1> ; (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER : 7999 <1> ; AND CYLINDER NUMBER HIGH BITS : 8000 <1> ; : 8001 <1> ; REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN : 8002 <1> ; INFORMATION. : 8003 <1> ; : 8004 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE : 8005 <1> ; ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION. : 8006 <1> ; : 8007 <1> ;------------------------------------------------------------------------------- 8008 <1> 8009 <1> SENSE_FAIL EQU 0FFH ; NOT IMPLEMENTED 8010 <1> NO_ERR EQU 0E0H ; STATUS ERROR/ERROR REGISTER=0 8011 <1> WRITE_FAULT EQU 0CCH ; WRITE FAULT ON SELECTED DRIVE 8012 <1> UNDEF_ERR EQU 0BBH ; UNDEFINED ERROR OCCURRED 8013 <1> NOT_RDY EQU 0AAH ; DRIVE NOT READY 8014 <1> TIME_OUT EQU 80H ; ATTACHMENT FAILED TO RESPOND 8015 <1> BAD_SEEK EQU 40H ; SEEK OPERATION FAILED 8016 <1> BAD_CNTLR EQU 20H ; CONTROLLER HAS FAILED 8017 <1> DATA_CORRECTED EQU 11H ; ECC CORRECTED DATA ERROR 8018 <1> BAD_ECC EQU 10H ; BAD ECC ON DISK READ 8019 <1> BAD_TRACK EQU 0BH ; NOT IMPLEMENTED 8020 <1> BAD_SECTOR EQU 0AH ; BAD SECTOR FLAG DETECTED 8021 <1> ;DMA_BOUNDARY EQU 09H ; DATA EXTENDS TOO FAR 8022 <1> INIT_FAIL EQU 07H ; DRIVE PARAMETER ACTIVITY FAILED 8023 <1> BAD_RESET EQU 05H ; RESET FAILED 8024 <1> ;RECORD_NOT_FND EQU 04H ; REQUESTED SECTOR NOT FOUND 8025 <1> ;BAD_ADDR_MARK EQU 02H ; ADDRESS MARK NOT FOUND 8026 <1> ;BAD_CMD EQU 01H ; BAD COMMAND PASSED TO DISK I/O 8027 <1> 8028 <1> ;-------------------------------------------------------- 8029 <1> ; : 8030 <1> ; FIXED DISK PARAMETER TABLE : 8031 <1> ; - THE TABLE IS COMPOSED OF A BLOCK DEFINED AS: : 8032 <1> ; : 8033 <1> ; +0 (1 WORD) - MAXIMUM NUMBER OF CYLINDERS : 8034 <1> ; +2 (1 BYTE) - MAXIMUM NUMBER OF HEADS : 8035 <1> ; +3 (1 WORD) - NOT USED/SEE PC-XT : 8036 <1> ; +5 (1 WORD) - STARTING WRITE PRECOMPENSATION CYL : 8037 <1> ; +7 (1 BYTE) - MAXIMUM ECC DATA BURST LENGTH : 8038 <1> ; +8 (1 BYTE) - CONTROL BYTE : 8039 <1> ; BIT 7 DISABLE RETRIES -OR- : 8040 <1> ; BIT 6 DISABLE RETRIES : 8041 <1> ; BIT 3 MORE THAN 8 HEADS : 8042 <1> ; +9 (3 BYTES)- NOT USED/SEE PC-XT : 8043 <1> ; +12 (1 WORD) - LANDING ZONE : 8044 <1> ; +14 (1 BYTE) - NUMBER OF SECTORS/TRACK : 8045 <1> ; +15 (1 BYTE) - RESERVED FOR FUTURE USE : 8046 <1> ; : 8047 <1> ; - TO DYNAMICALLY DEFINE A SET OF PARAMETERS : 8048 <1> ; BUILD A TABLE FOR UP TO 15 TYPES AND PLACE : 8049 <1> ; THE CORRESPONDING VECTOR INTO INTERRUPT 41 : 8050 <1> ; FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1. : 8051 <1> ; : 8052 <1> ;-------------------------------------------------------- 8053 <1> 8054 <1> ;-------------------------------------------------------- 8055 <1> ; : 8056 <1> ; HARDWARE SPECIFIC VALUES : 8057 <1> ; : 8058 <1> ; - CONTROLLER I/O PORT : 8059 <1> ; : 8060 <1> ; > WHEN READ FROM: : 8061 <1> ; HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU) : 8062 <1> ; HF_PORT+1 - GET ERROR REGISTER : 8063 <1> ; HF_PORT+2 - GET SECTOR COUNT : 8064 <1> ; HF_PORT+3 - GET SECTOR NUMBER : 8065 <1> ; HF_PORT+4 - GET CYLINDER LOW : 8066 <1> ; HF_PORT+5 - GET CYLINDER HIGH (2 BITS) : 8067 <1> ; HF_PORT+6 - GET SIZE/DRIVE/HEAD : 8068 <1> ; HF_PORT+7 - GET STATUS REGISTER : 8069 <1> ; : 8070 <1> ; > WHEN WRITTEN TO: : 8071 <1> ; HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) : 8072 <1> ; HF_PORT+1 - SET PRECOMPENSATION CYLINDER : 8073 <1> ; HF_PORT+2 - SET SECTOR COUNT : 8074 <1> ; HF_PORT+3 - SET SECTOR NUMBER : 8075 <1> ; HF_PORT+4 - SET CYLINDER LOW : 8076 <1> ; HF_PORT+5 - SET CYLINDER HIGH (2 BITS) : 8077 <1> ; HF_PORT+6 - SET SIZE/DRIVE/HEAD : 8078 <1> ; HF_PORT+7 - SET COMMAND REGISTER : 8079 <1> ; : 8080 <1> ;-------------------------------------------------------- 8081 <1> 8082 <1> ;HF_PORT EQU 01F0H ; DISK PORT 8083 <1> ;HF1_PORT equ 0170h 8084 <1> ;HF_REG_PORT EQU 03F6H 8085 <1> ;HF1_REG_PORT equ 0376h 8086 <1> 8087 <1> HDC1_BASEPORT equ 1F0h 8088 <1> HDC2_BASEPORT equ 170h 8089 <1> 8090 <1> align 2 8091 <1> 8092 <1> ;----- STATUS REGISTER 8093 <1> 8094 <1> ST_ERROR EQU 00000001B ; 8095 <1> ST_INDEX EQU 00000010B ; 8096 <1> ST_CORRCTD EQU 00000100B ; ECC CORRECTION SUCCESSFUL 8097 <1> ST_DRQ EQU 00001000B ; 8098 <1> ST_SEEK_COMPL EQU 00010000B ; SEEK COMPLETE 8099 <1> ST_WRT_FLT EQU 00100000B ; WRITE FAULT 8100 <1> ST_READY EQU 01000000B ; 8101 <1> ST_BUSY EQU 10000000B ; 8102 <1> 8103 <1> ;----- ERROR REGISTER 8104 <1> 8105 <1> ERR_DAM EQU 00000001B ; DATA ADDRESS MARK NOT FOUND 8106 <1> ERR_TRK_0 EQU 00000010B ; TRACK 0 NOT FOUND ON RECAL 8107 <1> ERR_ABORT EQU 00000100B ; ABORTED COMMAND 8108 <1> ; EQU 00001000B ; NOT USED 8109 <1> ERR_ID EQU 00010000B ; ID NOT FOUND 8110 <1> ; EQU 00100000B ; NOT USED 8111 <1> ERR_DATA_ECC EQU 01000000B 8112 <1> ERR_BAD_BLOCK EQU 10000000B 8113 <1> 8114 <1> 8115 <1> RECAL_CMD EQU 00010000B ; DRIVE RECAL (10H) 8116 <1> READ_CMD EQU 00100000B ; READ (20H) 8117 <1> WRITE_CMD EQU 00110000B ; WRITE (30H) 8118 <1> VERIFY_CMD EQU 01000000B ; VERIFY (40H) 8119 <1> FMTTRK_CMD EQU 01010000B ; FORMAT TRACK (50H) 8120 <1> INIT_CMD EQU 01100000B ; INITIALIZE (60H) 8121 <1> SEEK_CMD EQU 01110000B ; SEEK (70H) 8122 <1> DIAG_CMD EQU 10010000B ; DIAGNOSTIC (90H) 8123 <1> SET_PARM_CMD EQU 10010001B ; DRIVE PARMS (91H) 8124 <1> NO_RETRIES EQU 00000001B ; CHD MODIFIER (01H) 8125 <1> ECC_MODE EQU 00000010B ; CMD MODIFIER (02H) 8126 <1> BUFFER_MODE EQU 00001000B ; CMD MODIFIER (08H) 8127 <1> 8128 <1> ;MAX_FILE EQU 2 8129 <1> ;S_MAX_FILE EQU 2 8130 <1> MAX_FILE equ 4 ; 22/12/2014 8131 <1> S_MAX_FILE equ 4 ; 22/12/2014 8132 <1> 8133 <1> DELAY_1 EQU 25H ; DELAY FOR OPERATION COMPLETE 8134 <1> DELAY_2 EQU 0600H ; DELAY FOR READY 8135 <1> DELAY_3 EQU 0100H ; DELAY FOR DATA REQUEST 8136 <1> 8137 <1> HF_FAIL EQU 08H ; CMOS FLAG IN BYTE 0EH 8138 <1> 8139 <1> ;----- COMMAND BLOCK REFERENCE 8140 <1> 8141 <1> ;CMD_BLOCK EQU BP-8 ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS 8142 <1> ; (BP) POINTS TO COMMAND BLOCK TAIL 8143 <1> ; AS DEFINED BY THE "ENTER" PARMS 8144 <1> ; 19/12/2014 8145 <1> ORG_VECTOR equ 4*13h ; INT 13h vector 8146 <1> DISK_VECTOR equ 4*40h ; INT 40h vector (for floppy disks) 8147 <1> ;HDISK_INT equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 8148 <1> ;HDISK_INT1 equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 8149 <1> ;HDISK_INT2 equ 4*77h ; Secondary HDC - Hardware interrupt (IRQ15) 8150 <1> ;HF_TBL_VEC equ 4*41h ; Pointer to 1st fixed disk parameter table 8151 <1> ;HF1_TBL_VEC equ 4*46h ; Pointer to 2nd fixed disk parameter table 8152 <1> 8153 <1> align 2 8154 <1> 8155 <1> ;---------------------------------------------------------------- 8156 <1> ; FIXED DISK I/O SETUP : 8157 <1> ; : 8158 <1> ; - ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK : 8159 <1> ; - PERFORM POWER ON DIAGNOSTICS : 8160 <1> ; SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED : 8161 <1> ; : 8162 <1> ;---------------------------------------------------------------- 8163 <1> 8164 <1> ; 12/07/2022 8165 <1> ; 11/07/2022 8166 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8167 <1> 8168 <1> DISK_SETUP: 8169 <1> ;cli 8170 <1> ;;mov ax, ABS0 ; GET ABSOLUTE SEGMENT 8171 <1> ;xor ax, ax 8172 <1> ;mov ds, ax ; SET SEGMENT REGISTER 8173 <1> ;mov ax, [ORG_VECTOR] ; GET DISKETTE VECTOR 8174 <1> ;mov [DISK_VECTOR], ax ; INTO INT 40H 8175 <1> ;mov ax, [ORG_VECTOR+2] 8176 <1> ;mov [DISK_VECTOR+2], ax 8177 <1> ;mov word [ORG_VECTOR], DISK_IO ; FIXED DISK HANDLER 8178 <1> ;mov [ORG_VECTOR+2], cs 8179 <1> ; 1st controller (primary master, slave) - IRQ 14 8180 <1> ;;mov word [HDISK_INT], HD_INT ; FIXED DISK INTERRUPT 8181 <1> ;mov word [HDISK_INT1], HD_INT ; 8182 <1> ;;mov [HDISK_INT+2], cs 8183 <1> ;mov [HDISK_INT1+2], cs 8184 <1> ; 2nd controller (secondary master, slave) - IRQ 15 8185 <1> ;mov word [HDISK_INT2], HD1_INT ; 8186 <1> ;mov [HDISK_INT2+2], cs 8187 <1> ; 8188 <1> ;;mov word [HF_TBL_VEC], HD0_DPT ; PARM TABLE DRIVE 80 8189 <1> ;;mov word [HF_TBL_VEC+2], DPT_SEGM 8190 <1> ;;mov word [HF1_TBL_VEC], HD1_DPT ; PARM TABLE DRIVE 81 8191 <1> ;;mov word [HF1_TBL_VEC+2], DPT_SEGM 8192 <1> ;push cs 8193 <1> ;pop ds 8194 <1> ;mov word [HDPM_TBL_VEC],HD0_DPT ; PARM TABLE DRIVE 80h 8195 <1> ;mov word [HDPM_TBL_VEC+2],DPT_SEGM 8196 00001F10 C705[00680000]0000- <1> mov dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT 8197 00001F18 0900 <1> 8198 <1> ;mov word [HDPS_TBL_VEC],HD1_DPT ; PARM TABLE DRIVE 81h 8199 <1> ;mov word [HDPS_TBL_VEC+2],DPT_SEGM 8200 00001F1A C705[04680000]2000- <1> mov dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT 8201 00001F22 0900 <1> 8202 <1> ;mov word [HDSM_TBL_VEC],HD2_DPT ; PARM TABLE DRIVE 82h 8203 <1> ;mov word [HDSM_TBL_VEC+2],DPT_SEGM 8204 00001F24 C705[08680000]4000- <1> mov dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT 8205 00001F2C 0900 <1> 8206 <1> ;mov word [HDSS_TBL_VEC],HD3_DPT ; PARM TABLE DRIVE 83h 8207 <1> ;mov word [HDSS_TBL_VEC+2],DPT_SEGM 8208 00001F2E C705[0C680000]6000- <1> mov dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT 8209 00001F36 0900 <1> 8210 <1> ; 8211 <1> ;;in al, INTB01 ; TURN ON SECOND INTERRUPT CHIP 8212 <1> ;;;and al, 0BFh 8213 <1> ;;and al, 3Fh ; enable IRQ 14 and IRQ 15 8214 <1> ;;;JMP $+2 8215 <1> ;;IODELAY 8216 <1> ;;out INTB01, al 8217 <1> ;;IODELAY 8218 <1> ;;in al, INTA01 ; LET INTERRUPTS PASS THRU TO 8219 <1> ;;and al, 0FBh ; SECOND CHIP 8220 <1> ;;;JMP $+2 8221 <1> ;;IODELAY 8222 <1> ;;out INTA01, al 8223 <1> ; 8224 <1> ;sti 8225 <1> ;;push ds ; MOVE ABS0 POINTER TO 8226 <1> ;;pop es ; EXTRA SEGMENT POINTER 8227 <1> ;;;call DDS ; ESTABLISH DATA SEGMENT 8228 <1> ;;mov byte [DISK_STATUS1],0 ; RESET THE STATUS INDICATOR 8229 <1> ;;mov byte [HF_NUM],0 ; ZERO NUMBER OF FIXED DISKS 8230 <1> ;;mov byte [CONTROL_BYTE],0 8231 <1> ;;mov byte [PORT_OFF],0 ; ZERO CARD OFFSET 8232 <1> ; 20/12/2014 - private code by Erdogan Tan 8233 <1> ; (out of original PC-AT, PC-XT BIOS code) 8234 <1> ;mov si, hd0_type 8235 00001F38 BE[8E620000] <1> mov esi, hd0_type 8236 <1> ;;mov cx, 4 8237 <1> ;mov ecx, 4 8238 <1> ; 11/07/2022 8239 00001F3D 29C9 <1> sub ecx, ecx 8240 00001F3F B104 <1> mov cl, 4 8241 <1> hde_l: 8242 00001F41 AC <1> lodsb 8243 00001F42 3C80 <1> cmp al, 80h ; 8?h = existing 8244 00001F44 7206 <1> jb short _L4 8245 00001F46 FE05[FC670000] <1> inc byte [HF_NUM] ; + 1 hard (fixed) disk drives 8246 <1> _L4: ; 26/02/2015 8247 00001F4C E2F3 <1> loop hde_l 8248 <1> ;_L4: ; 0 <= [HF_NUM] =< 4 8249 <1> ;L4: 8250 <1> ; 8251 <1> ;; 31/12/2014 - cancel controller diagnostics here 8252 <1> ;;;mov cx, 3 ; 26/12/2014 (Award BIOS 1999) 8253 <1> ;;mov cl, 3 8254 <1> ;; 8255 <1> ;;mov dl, 80h ; CHECK THE CONTROLLER 8256 <1> ;;hdc_dl: 8257 <1> ;;mov ah, 14h ; USE CONTROLLER DIAGNOSTIC COMMAND 8258 <1> ;;int 13h ; CALL BIOS WITH DIAGNOSTIC COMMAND 8259 <1> ;;;jc short CTL_ERRX ; DISPLAY ERROR MESSAGE IF BAD RETURN 8260 <1> ;;;jc short POD_DONE ;22/12/2014 8261 <1> ;;jnc short hdc_reset0 8262 <1> ;;loop hdc_dl 8263 <1> ;;; 27/12/2014 8264 <1> ;;stc 8265 <1> ;;retn 8266 <1> ; 8267 <1> ;;hdc_reset0: 8268 <1> ; 18/01/2015 8269 00001F4E 8A0D[FC670000] <1> mov cl, [HF_NUM] 8270 00001F54 20C9 <1> and cl, cl 8271 00001F56 740D <1> jz short POD_DONE 8272 <1> ; 8273 00001F58 B27F <1> mov dl, 7Fh 8274 <1> hdc_reset1: 8275 00001F5A FEC2 <1> inc dl 8276 <1> ;; 31/12/2015 8277 <1> ;;push dx 8278 <1> ;;push cx 8279 <1> ;;push ds 8280 <1> ;;sub ax, ax 8281 <1> ;;mov ds, ax 8282 <1> ;;mov ax, [TIMER_LOW] ; GET START TIMER COUNTS 8283 <1> ;;pop ds 8284 <1> ;;mov bx, ax 8285 <1> ;;add ax, 6*182 ; 60 SECONDS* 18.2 8286 <1> ;;mov cx, ax 8287 <1> ;;mov word [wait_count], 0 ; 22/12/2014 (reset wait counter) 8288 <1> ;; 8289 <1> ;; 31/12/2014 - cancel HD_RESET_1 8290 <1> ;;call HD_RESET_1 ; SET UP DRIVE 0, (1,2,3) 8291 <1> ;;pop cx 8292 <1> ;;pop dx 8293 <1> ;; 8294 <1> ; 18/01/2015 8295 <1> ;mov ah, 0Dh ; ALTERNATE RESET 8296 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8297 <1> ;mov ah, 5 ; ALTERNATE RESET 8298 <1> ;;int 13h 8299 <1> ;call int13h 8300 <1> ; 12/07/2022 8301 00001F5C 30C0 <1> xor al, al ; reset 8302 00001F5E E803000000 <1> call DISK_IO 8303 <1> ; 8304 00001F63 E2F5 <1> loop hdc_reset1 8305 <1> POD_DONE: 8306 00001F65 C3 <1> RETn 8307 <1> 8308 <1> ;---------------------------------------- 8309 <1> ; FIXED DISK BIOS ENTRY POINT : 8310 <1> ;---------------------------------------- 8311 <1> 8312 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8313 <1> ; ((Direct call instead of int 13h simulation)) 8314 <1> ; 8315 <1> ; Function in AL 8316 <1> ; 0 = reset 8317 <1> ; 1 = read 8318 <1> ; 2 = write 8319 <1> ; Disk drive number in DL 8320 <1> ; 0 & 1 = floppy disks 8321 <1> ; 80h .. 83h = hard disks 8322 <1> ; Sector address (LBA) in ECX 8323 <1> ; Buffer address in EBX 8324 <1> ; R/W sector count is (always) 1 8325 <1> ; 8326 <1> ; Return: 8327 <1> ; Status in AH (>0 = error code) 8328 <1> ; if CF = 1 -> error code in AH 8329 <1> ; if CF = 0 -> successful 8330 <1> ; AL = undefined 8331 <1> ; 8332 <1> ; Modified registers: (only) EAX 8333 <1> 8334 <1> 8335 <1> ; 11/07/2022 8336 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8337 <1> 8338 <1> DISK_IO: 8339 <1> ; 11/07/2022 8340 <1> ; save registers 8341 00001F66 57 <1> push edi ; ANY 8342 00001F67 56 <1> push esi ; ANY 8343 00001F68 53 <1> push ebx ; BUFFER ADDRESS 8344 00001F69 51 <1> push ecx ; SECTOR ADDRESS (LBA) 8345 00001F6A 52 <1> push edx ; DRIVE NUMBER (DL) 8346 <1> 8347 <1> ;cmp dl, 80h ; TEST FOR FIXED DISK DRIVE 8348 <1> ;;jae short A1 ; YES, HANDLE HERE 8349 <1> ;;;;int 40H ; DISKETTE HANDLER 8350 <1> ;;;call int40h 8351 <1> ;;jb DISKETTE_IO_1 8352 <1> ;; 24/12/2021 8353 <1> ;jnb short A1 8354 <1> ;jmp DISKETTE_IO_1 8355 <1> 8356 <1> ; 11/07/2022 8357 00001F6B 80FA80 <1> cmp dl, 80h 8358 00001F6E 730B <1> jae short A1 8359 <1> 8360 00001F70 E8CAF6FFFF <1> call DISKETTE_IO_1 8361 <1> 8362 <1> DISK_IO_RTN: 8363 <1> ; restore registers 8364 00001F75 5A <1> pop edx 8365 00001F76 59 <1> pop ecx 8366 00001F77 5B <1> pop ebx 8367 00001F78 5E <1> pop esi 8368 00001F79 5F <1> pop edi 8369 00001F7A C3 <1> retn 8370 <1> 8371 <1> ;RET_2: 8372 <1> ; retf 4 ; BACK TO CALLER 8373 <1> 8374 <1> A1: 8375 <1> ; 11/07/2022 8376 <1> ;sti ; ENABLE INTERRUPTS 8377 <1> ;cmp dl, (80h + S_MAX_FILE - 1) 8378 <1> ;ja short RET_2 8379 <1> 8380 <1> ; 18/01/2015 8381 <1> ;;or ah, ah 8382 <1> ;or al, al ; 11/07/2022 (reset function) 8383 <1> ;jz short A3 ; 08/07/2022 8384 <1> 8385 <1> ;;cmp ah, 5 ; Alternate reset 8386 <1> ;cmp al, 5 ; 11/07/2022 8387 <1> ;je short A2 8388 <1> 8389 <1> ; 11/07/2022 - no need to check 8390 <1> ; (only kernel calls diskio functions) 8391 <1> ;;cmp ah, M1L/4 ; cmp ah, 6 8392 <1> ;jb short A3 8393 <1> ;; BAD COMMAND 8394 <1> ;mov byte [DISK_STATUS1], BAD_CMD 8395 <1> ;RET_2: 8396 <1> ;retf 4 8397 <1> 8398 <1> ; 11/07/2022 8399 <1> ;stc 8400 <1> ;retn 8401 <1> A2: 8402 <1> ;sub ah, ah ; Reset 8403 <1> ; 11/07/2022 8404 <1> ;sub al, al 8405 <1> A3: 8406 <1> ; SAVE REGISTERS DURING OPERATION 8407 00001F7B C8080000 <1> enter 8,0 ; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK 8408 <1> 8409 <1> ; 11/07/2022 8410 <1> ; 08/07/2022 8411 <1> ;push ebx ; IN THE STACK, THE COMMAND BLOCK IS: 8412 <1> ;push ecx ; @CMD_BLOCK == BYTE PTR [EBP]-8 8413 <1> ;push edx 8414 <1> ;push esi 8415 <1> ;push edi 8416 <1> 8417 00001F7F E80D000000 <1> call DISK_IO_CONT ; PERFORM THE OPERATION 8418 <1> 8419 00001F84 C9 <1> leave ; 11/07/2022 8420 <1> 8421 00001F85 8A25[FB670000] <1> mov ah, [DISK_STATUS1] ; GET STATUS FROM OPERATION 8422 00001F8B 80FC01 <1> cmp ah, 1 ; SET THE CARRY FLAG TO INDICATE 8423 00001F8E F5 <1> cmc ; SUCCESS OR FAILURE 8424 <1> 8425 <1> ;pop edi ; RESTORE REGISTERS 8426 <1> ;pop esi 8427 <1> ;pop edx 8428 <1> ;pop ecx 8429 <1> ;pop ebx 8430 <1> 8431 <1> ;leave ; ADJUST (ESP) AND RESTORE (EBP) 8432 <1> 8433 <1> ; 11/07/2022 8434 <1> ;retf 4 ; THROW AWAY SAVED FLAGS 8435 <1> 8436 00001F8F EBE4 <1> jmp short DISK_IO_RTN 8437 <1> 8438 <1> DISK_IO_CONT: 8439 <1> ; 17/07/2022 8440 <1> ; 11/07/2022 8441 <1> ; INPUT: 8442 <1> ; AL = 0 : reset 8443 <1> ; AL = 1 : read 8444 <1> ; Al = 2 : write 8445 <1> ; 8446 <1> ; 10/07/2022 8447 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8448 <1> SU0: 8449 00001F91 C605[FB670000]00 <1> mov byte [DISK_STATUS1], 0 ; RESET THE STATUS INDICATOR 8450 <1> ; 10/07/2022 8451 00001F98 89DE <1> mov esi, ebx ; 21/02/2015 ; DATA (BUFFER) ADDRESS 8452 <1> 8453 00001F9A 8A1D[FC670000] <1> mov bl, [HF_NUM] ; GET NUMBER OF DRIVES 8454 00001FA0 80E27F <1> and dl, 7Fh ; GET DRIVE AS 0 OR 1 8455 <1> ; (get drive number as 0 to 3) 8456 00001FA3 38D3 <1> cmp bl, dl 8457 <1> ;;jbe BAD_COMMAND_POP ; INVALID DRIVE 8458 <1> ;jbe BAD_COMMAND ;; 14/02/2015 8459 <1> ; 24/12/2021 8460 00001FA5 7705 <1> ja short su0_su1 8461 00001FA7 E98D000000 <1> jmp BAD_COMMAND 8462 <1> su0_su1: 8463 <1> ;;03/01/2015 8464 00001FAC 29DB <1> sub ebx, ebx 8465 00001FAE 88D3 <1> mov bl, dl 8466 00001FB0 883D[10680000] <1> mov [LBAMode], bh ; 0 8467 <1> ;test byte [ebx+hd0_type], 1 ; LBA ready ? 8468 <1> ;jz short su1 ; no 8469 <1> ;inc byte [LBAMode] 8470 <1> ;su1: 8471 <1> ; 21/02/2015 (32 bit modification) 8472 <1> ; 04/01/2015 8473 <1> ;push ax ; *** 8474 <1> ; 24/12/2021 8475 00001FB6 50 <1> push eax ; *** ; function (in AL) ; 11/07/2022 8476 <1> ; 24/12/2021 8477 00001FB7 52 <1> push edx ; * 8478 00001FB8 50 <1> push eax ; function (in AL) ; 11/07/2022 8479 00001FB9 E8CA030000 <1> CALL GET_VEC ; GET DISK PARAMETERS 8480 <1> ; 02/02/2015 8481 00001FBE 668B4310 <1> mov ax, [ebx+16] ; I/O port base address (1F0h, 170h) 8482 00001FC2 66A3[82620000] <1> mov [HF_PORT], ax 8483 00001FC8 668B5312 <1> mov dx, [ebx+18] ; control port address (3F6h, 376h) 8484 00001FCC 668915[84620000] <1> mov [HF_REG_PORT], dx 8485 00001FD3 8A4314 <1> mov al, [ebx+20] ; head register upper nibble (A0h,B0h,E0h,F0h) 8486 <1> ; 23/02/2015 8487 00001FD6 A840 <1> test al, 40h ; LBA bit (bit 6) 8488 00001FD8 7406 <1> jz short su1 8489 00001FDA FE05[10680000] <1> inc byte [LBAMode] ; 1 8490 <1> su1: 8491 00001FE0 C0E804 <1> shr al, 4 8492 00001FE3 2401 <1> and al, 1 8493 00001FE5 A2[86620000] <1> mov [hf_m_s], al 8494 <1> ; 8495 <1> ; 03/01/2015 8496 00001FEA 8A4308 <1> mov al, [ebx+8] ; GET CONTROL BYTE MODIFIER 8497 <1> ;mov dx, [HF_REG_PORT] ; Device Control register 8498 00001FED EE <1> out dx, al ; SET EXTRA HEAD OPTION 8499 <1> ; Control Byte: (= 08h, here) 8500 <1> ; bit 0 - 0 8501 <1> ; bit 1 - nIEN (1 = disable irq) 8502 <1> ; bit 2 - SRST (software RESET) 8503 <1> ; bit 3 - use extra heads (8 to 15) 8504 <1> ; -always set to 1- 8505 <1> ; (bits 3 to 7 are reserved 8506 <1> ; for ATA devices) 8507 00001FEE 8A25[FD670000] <1> mov ah, [CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 8508 00001FF4 80E4C0 <1> and ah, 0C0h ; CONTROL BYTE 8509 00001FF7 08C4 <1> or ah, al 8510 00001FF9 8825[FD670000] <1> mov [CONTROL_BYTE], ah 8511 <1> ; 04/01/2015 8512 <1> ;pop ax 8513 <1> ; 24/12/2021 8514 00001FFF 58 <1> pop eax ; function (in AL) ; 11/07/2022 8515 <1> ;pop dx ; * ;; 14/02/2015 8516 <1> ; 24/12/2021 8517 00002000 5A <1> pop edx ; * 8518 <1> ;and ah, ah ; Reset function ? 8519 00002001 20C0 <1> and al, al ; 11/07/2022 8520 00002003 7506 <1> jnz short su2 8521 <1> ;pop ax ; *** 8522 <1> ; 24/12/2021 8523 00002005 58 <1> pop eax ; *** 8524 <1> ;;pop bx 8525 00002006 E9EA000000 <1> jmp DISK_RESET 8526 <1> su2: 8527 <1> ; 11/07/2022 8528 <1> ; ecx = sector address (lba) 8529 <1> ; dl = hard disk drive number (80h, 81h .. 83h) 8530 <1> ; al = function (0 = read, 1 = write) 8531 <1> 8532 0000200B 803D[10680000]00 <1> cmp byte [LBAMode], 0 8533 00002012 7620 <1> jna short su3 ; convert LBA address to CHS parameters 8534 <1> 8535 <1> ; ; 02/02/2015 (LBA read/write function calls) 8536 <1> ; ;cmp ah, 1Bh 8537 <1> ; cmp ah, 3 ; 08/07/2022 8538 <1> ; jb short lbarw1 8539 <1> ; ;;cmp ah, 1Ch 8540 <1> ; ;cmp ah, 4 ; 08/07/2022 8541 <1> ; ;ja short invldfnc 8542 <1> ; ;;pop dx ; * ; 14/02/2015 8543 <1> ; ;mov ax, cx ; Lower word of LBA address (bits 0-15) 8544 <1> 8545 00002014 89C8 <1> mov eax, ecx ; LBA address (21/02/2015) 8546 <1> 8547 <1> ; 11/07/2022 8548 <1> ;; 14/02/2015 8549 <1> ;mov cl, dl ; 14/02/2015 8550 <1> 8551 <1> ;;mov dx, bx 8552 <1> ;mov dx, si ; higher word of LBA address (bits 16-23) 8553 <1> ;;mov bx, di 8554 <1> ;mov si, di ; Buffer offset 8555 <1> 8556 <1> ; 11/07/2022 8557 <1> ;jmp short lbarw2 8558 <1> 8559 <1> ;lbarw1: 8560 <1> ; ; convert CHS to LBA 8561 <1> ; ; 8562 <1> ; ; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM 8563 <1> ; ; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track 8564 <1> ; ; + Sector - 1 8565 <1> ; ;push dx ; * ;; 14/02/2015 8566 <1> ; ; 24/12/2021 8567 <1> ; push edx ; * 8568 <1> ; ;xor dh, dh 8569 <1> ; xor edx, edx 8570 <1> ; mov dl, [ebx+14] ; sectors per track (logical) 8571 <1> ; ;xor ah, ah 8572 <1> ; xor eax, eax 8573 <1> ; mov al, [ebx+2] ; heads (logical) 8574 <1> ; dec al 8575 <1> ; ;inc ax ; 0 = 256 8576 <1> ; inc eax ; 24/12/2021 8577 <1> ; mul dx 8578 <1> ; ; AX = # of Heads * Sectors/Track 8579 <1> ; mov dx, cx 8580 <1> ; ;and cx, 3Fh ; sector (1 to 63) 8581 <1> ; and ecx, 3fh 8582 <1> ; xchg dl, dh 8583 <1> ; shr dh, 6 8584 <1> ; ; DX = cylinder (0 to 1023) 8585 <1> ; ;mul dx 8586 <1> ; ; DX:AX = # of Heads * Sectors/Track * Cylinder 8587 <1> ; mul edx 8588 <1> ; dec cl ; sector - 1 8589 <1> ; ;add ax, cx 8590 <1> ; ;adc dx, 0 8591 <1> ; ; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1 8592 <1> ; add eax, ecx 8593 <1> ; ;pop cx ; * ; ch = head, cl = drive number (zero based) 8594 <1> ; ; 24/12/2021 8595 <1> ; pop ecx ; * ; ch = head, cl = drive number (zero based) 8596 <1> ; ;push dx 8597 <1> ; ;push ax 8598 <1> ; push eax 8599 <1> ; mov al, [ebx+14] ; sectors per track (logical) 8600 <1> ; mul ch 8601 <1> ; ; AX = Head * Sectors/Track 8602 <1> ; cwd 8603 <1> ; ;pop dx 8604 <1> ; pop edx 8605 <1> ; ;add ax, dx 8606 <1> ; ;pop dx 8607 <1> ; ;adc dx, 0 ; add carry bit 8608 <1> ; add eax, edx 8609 <1> ; 8610 <1> ;lbarw2: 8611 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8612 <1> 8613 00002016 29D2 <1> sub edx, edx ; 21/02/2015 8614 <1> 8615 <1> ; 11/07/2022 8616 <1> ;mov dl, cl ; 21/02/2015 8617 <1> 8618 00002018 C645F800 <1> mov byte [CMD_BLOCK], 0 ; Features Register 8619 <1> ; NOTE: Features register (1F1h, 171h) 8620 <1> ; is not used for ATA device R/W functions. 8621 <1> ; It is old/obsolete 'write precompensation' 8622 <1> ; register and error register 8623 <1> ; for old ATA/IDE devices. 8624 <1> ; 18/01/2014 8625 <1> ;mov ch, [hf_m_s] ; Drive 0 (master) or 1 (slave) 8626 0000201C 8A0D[86620000] <1> mov cl, [hf_m_s] 8627 <1> ;shl ch, 4 ; bit 4 (drive bit) 8628 <1> ;or ch, 0E0h ; bit 5 = 1 8629 <1> ; bit 6 = 1 = LBA mode 8630 <1> ; bit 7 = 1 8631 00002022 80C90E <1> or cl, 0Eh ; 1110b 8632 <1> ;and dh, 0Fh ; LBA byte 4 (bits 24 to 27) 8633 00002025 25FFFFFF0F <1> and eax, 0FFFFFFFh 8634 0000202A C1E11C <1> shl ecx, 28 ; 21/02/2015 8635 <1> ;or dh, ch 8636 0000202D 09C8 <1> or eax, ecx 8637 <1> ;;mov [CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7) 8638 <1> ; (Sector Number Register) 8639 <1> ;;mov [CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15) 8640 <1> ; (Cylinder Low Register) 8641 <1> ;mov [CMD_BLOCK+2], ax ; LBA byte 1, 2 8642 <1> ;mov [CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23) 8643 <1> ; (Cylinder High Register) 8644 <1> ;;mov [CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27) 8645 <1> ; (Drive/Head Register) 8646 <1> 8647 <1> ;mov [CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits 8648 0000202F 8945FA <1> mov [CMD_BLOCK+2], eax ; 21/02/2015 8649 <1> ;14/02/2015 8650 <1> ;mov dl, cl ; Drive number (INIT_DRV) 8651 00002032 EB3D <1> jmp short su4 8652 <1> su3: 8653 <1> ; 02/02/2015 8654 <1> ; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 8655 <1> ;cmp ah, 14h 8656 <1> ;jna short chsfnc 8657 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8658 <1> ;cmp ah, 2 8659 <1> ;jna short chsfnc 8660 <1> ; 11/07/2022 8661 <1> ; (al = function, read = 1 or write = 2) 8662 00002034 3C02 <1> cmp al, 2 8663 00002036 760B <1> jna short chsfnc 8664 <1> invldfnc: 8665 <1> ; 14/02/2015 8666 <1> ;pop es ; ** 8667 <1> ;pop ax ; *** 8668 <1> ; 24/12/2021 8669 00002038 58 <1> pop eax ; *** 8670 <1> ;;jmp short BAD_COMMAND_POP 8671 <1> ; 11/07/2022 8672 <1> ;jmp short BAD_COMMAND 8673 <1> 8674 <1> ; 11/07/2022 8675 <1> BAD_COMMAND: 8676 00002039 C605[FB670000]01 <1> mov byte [DISK_STATUS1], BAD_CMD ; COMMAND ERROR 8677 <1> ;mov al, 0 8678 00002040 28C0 <1> sub al, al ; 0 8679 00002042 C3 <1> retn 8680 <1> 8681 <1> chsfnc: 8682 00002043 668B4305 <1> mov ax, [ebx+5] ; GET WRITE PRE-COMPENSATION CYLINDER 8683 <1> ;shr ax, 2 8684 <1> ; 17/07/2022 8685 00002047 C1E802 <1> shr eax, 2 8686 0000204A 8845F8 <1> mov [CMD_BLOCK], al 8687 <1> ; 8688 <1> ;;mov al, [ebx+8] ; GET CONTROL BYTE MODIFIER 8689 <1> ;;push edx ; * 8690 <1> ;;mov dx, [HF_REG_PORT] 8691 <1> ;;out dx, al ; SET EXTRA HEAD OPTION 8692 <1> ;;pop edx ; * 8693 <1> ;;mov ah, [CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 8694 <1> ;;and ah, 0C0h ; CONTROL BYTE 8695 <1> ;;or ah, al 8696 <1> ;;mov [CONTROL_BYTE], ah 8697 <1> ; 8698 0000204D 88C8 <1> mov al, cl ; GET SECTOR NUMBER 8699 0000204F 243F <1> and al, 3Fh 8700 00002051 8845FA <1> mov [CMD_BLOCK+2], al 8701 00002054 886DFB <1> mov [CMD_BLOCK+3], ch ; GET CYLINDER NUMBER 8702 00002057 88C8 <1> mov al, cl 8703 00002059 C0E806 <1> shr al, 6 8704 0000205C 8845FC <1> mov [CMD_BLOCK+4], al ; CYLINDER HIGH ORDER 2 BITS 8705 <1> ;;05/01/2015 8706 <1> ;;mov al, dl ; DRIVE NUMBER 8707 0000205F A0[86620000] <1> mov al, [hf_m_s] 8708 00002064 C0E004 <1> shl al, 4 8709 00002067 80E60F <1> and dh, 0Fh ; HEAD NUMBER 8710 0000206A 08F0 <1> or al, dh 8711 0000206C 0CA0 <1> or al, 80h+20h ; ECC AND 512 BYTE SECTORS 8712 0000206E 8845FD <1> mov [CMD_BLOCK+5], al ; ECC/SIZE/DRIVE/HEAD 8713 <1> su4: 8714 <1> ;; 14/02/2015 8715 <1> ;;pop ax 8716 <1> ;;mov [CMD_BLOCK+1], AL ; SECTOR COUNT 8717 <1> ;;push ax 8718 <1> ;;mov al, ah ; GET INTO LOW BYTE 8719 <1> ;;xor ah, ah ; ZERO HIGH BYTE 8720 <1> ;;sal ax, 1 ; *2 FOR TABLE LOOKUP 8721 <1> ;pop ax ; *** 8722 <1> ; 24/12/2021 8723 00002071 58 <1> pop eax ; *** ; function (in AL) ; 11/07/2022 8724 <1> 8725 <1> ;mov [CMD_BLOCK+1], al 8726 00002072 C645F901 <1> mov byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w) 8727 <1> 8728 <1> ; 11/07/2022 8729 <1> ;mov ebx, esi 8730 <1> ; (esi = buffer address) 8731 <1> 8732 00002076 3C02 <1> cmp al, 2 8733 00002078 7433 <1> je short DISK_WRITE 8734 <1> 8735 <1> ;jmp short DISK_READ 8736 <1> 8737 <1> ; ;xor ebx, ebx 8738 <1> ; ;mov bl, ah 8739 <1> ; 8740 <1> ; ;xor bh, bh 8741 <1> ; ;sal bx, 1 8742 <1> ; sal ebx, 2 ; 32 bit offset (21/02/2015) 8743 <1> ; ;;mov si, ax ; PUT INTO SI FOR BRANCH 8744 <1> ; ;;cmp ax, M1L ; TEST WITHIN RANGE 8745 <1> ; ;;jnb short BAD_COMMAND_POP 8746 <1> ; ; 08/07/2022 8747 <1> ; ;cmp ebx, M1L 8748 <1> ; ;jnb short BAD_COMMAND 8749 <1> ; 8750 <1> ; xchg ebx, esi 8751 <1> ; 8752 <1> ; ;;;pop ax ; RESTORE AX 8753 <1> ; ;;;pop bx ; AND DATA ADDRESS 8754 <1> ; 8755 <1> ; ;;push cx 8756 <1> ; ;;push ax ; ADJUST ES:BX 8757 <1> ; ;mov cx, bx ; GET 3 HIGH ORDER NIBBLES OF BX 8758 <1> ; ;shr cx, 4 8759 <1> ; ;mov ax, es 8760 <1> ; ;add ax, cx 8761 <1> ; ;mov es, ax 8762 <1> ; ;and bx, 000Fh ; ES:BX CHANGED TO ES:000X 8763 <1> ; ;;pop ax 8764 <1> ; ;;pop cx 8765 <1> ; 8766 <1> ; jmp dword [esi+M1] 8767 <1> 8768 <1> ;;BAD_COMMAND_POP: 8769 <1> ;; pop ax 8770 <1> ;; pop bx 8771 <1> ; 8772 <1> ; ; 11/07/2022 8773 <1> ;BAD_COMMAND: 8774 <1> ; mov byte [DISK_STATUS1], BAD_CMD ; COMMAND ERROR 8775 <1> ; ;mov al, 0 8776 <1> ; sub al, al ; 0 8777 <1> ; retn 8778 <1> 8779 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8780 <1> 8781 <1> ;---------------------------------------- 8782 <1> ; DISK READ ROUTINE (AH = 01H) : 8783 <1> ;---------------------------------------- 8784 <1> ; 8785 <1> DISK_READ: 8786 0000207A C645FE20 <1> mov byte [CMD_BLOCK+6], READ_CMD 8787 <1> ;jmp COMMANDI 8788 <1> 8789 <1> ; 16/07/2022 8790 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8791 <1> 8792 <1> ;---------------------------------------- 8793 <1> ; COMMANDI : 8794 <1> ; REPEATEDLY INPUTS DATA TILL : 8795 <1> ; NSECTOR RETURNS ZERO : 8796 <1> ;---------------------------------------- 8797 <1> COMMANDI: 8798 <1> ; 11/07/2022 8799 <1> ; (check 64K boundary is not needed) 8800 <1> ;call CHECK_DMA ; CHECK 64K BOUNDARY ERROR 8801 <1> ;jc short CMD_ABORT 8802 <1> 8803 <1> ;mov di, bx 8804 <1> ; 11/07/2022 8805 <1> ; (esi = buffer address) 8806 <1> ;mov edi, ebx ; 21/02/2015 8807 0000207E 89F7 <1> mov edi, esi ; 11/07/2022 8808 <1> 8809 00002080 E8AE010000 <1> call COMMAND ; OUTPUT COMMAND 8810 00002085 7525 <1> jnz short CMD_ABORT 8811 <1> CMD_I1: 8812 00002087 E819020000 <1> call _WAIT ; WAIT FOR DATA REQUEST INTERRUPT 8813 0000208C 751E <1> jnz short TM_OUT ; TIME OUT 8814 <1> ;;mov cx,256 ; SECTOR SIZE IN WORDS 8815 <1> ;mov ecx, 256 ; 21/02/2015 8816 0000208E 29C9 <1> sub ecx, ecx 8817 00002090 FEC5 <1> inc ch 8818 <1> ; ecx = 256 8819 <1> ;mov dx, HF_PORT 8820 00002092 668B15[82620000] <1> mov dx, [HF_PORT] 8821 00002099 FA <1> cli 8822 0000209A FC <1> cld 8823 0000209B F3666D <1> rep insw ; GET THE SECTOR 8824 0000209E FB <1> sti 8825 <1> 8826 <1> ;test byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT 8827 <1> ;jz short CMD_I3 8828 <1> ;call WAIT_DRQ ; WAIT FOR DATA REQUEST 8829 <1> ;jc short TM_OUT 8830 <1> ;;mov dx, HF_PORT 8831 <1> ;mov dx,[HF_PORT] 8832 <1> ;xor ecx, ecx 8833 <1> ;;mov ecx, 4 ; mov cx, 4 ; OUTPUT THE ECC BYTES 8834 <1> ;mov cl, 4 8835 <1> ;CMD_I2: 8836 <1> ;inc al, dx 8837 <1> ;mov [edi], al ; 21/02/2015 8838 <1> ;inc edi 8839 <1> ;loop CMD_I2 8840 <1> CMD_I3: 8841 <1> ; 16/07/2022 8842 <1> ; wait for 400 ns 8843 0000209F 80C207 <1> add dl, 7 8844 000020A2 EC <1> in al, dx 8845 000020A3 EC <1> in al, dx 8846 000020A4 EC <1> in al, dx 8847 <1> ; 8848 000020A5 E817010000 <1> call CHECK_STATUS 8849 000020AA 7500 <1> jnz short CMD_ABORT ; ERROR RETURNED 8850 <1> ; 11/07/2022 8851 <1> ; (sector count = 1) 8852 <1> ;dec byte [CMD_BLOCK+1] ; CHECK FOR MORE 8853 <1> ;jnz SHORT CMD_I1 8854 <1> CMD_ABORT: 8855 <1> TM_OUT: 8856 000020AC C3 <1> retn 8857 <1> 8858 <1> ;--------------------------------------------------- 8859 <1> 8860 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8861 <1> 8862 <1> ;---------------------------------------- 8863 <1> ; DISK WRITE ROUTINE (AH = 02H) : 8864 <1> ;---------------------------------------- 8865 <1> 8866 <1> DISK_WRITE: 8867 000020AD C645FE30 <1> mov byte [CMD_BLOCK+6], WRITE_CMD 8868 <1> ;JMP COMMANDO 8869 <1> 8870 <1> ; 16/07/2022 - Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 8871 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8872 <1> 8873 <1> ;---------------------------------------- 8874 <1> ; COMMANDO : 8875 <1> ; REPEATEDLY OUTPUTS DATA TILL : 8876 <1> ; NSECTOR RETURNS ZERO : 8877 <1> ;---------------------------------------- 8878 <1> COMMANDO: 8879 <1> ; 11/07/2022 8880 <1> ; (check 64K boundary is not needed) 8881 <1> ;call CHECK_DMA ; CHECK 64K BOUNDARY ERROR 8882 <1> ;jc short CMD_ABORT 8883 <1> CMD_OF: 8884 <1> ; 11/07/2022 8885 <1> ; (esi = ebx = buffer address) 8886 <1> ;mov esi, ebx ; 21/02/2015 8887 000020B1 E87D010000 <1> call COMMAND ; OUTPUT COMMAND 8888 000020B6 75F4 <1> jnz short CMD_ABORT 8889 000020B8 E83F020000 <1> call WAIT_DRQ ; WAIT FOR DATA REQUEST 8890 000020BD 72ED <1> jc short TM_OUT ; TOO LONG 8891 <1> CMD_O1: 8892 <1> ; 16/07/2022 8893 000020BF 668B15[82620000] <1> mov dx, [HF_PORT] 8894 <1> 8895 <1> ; 10/07/2022 8896 <1> ;mov ecx, 256 ; 21/02/2015 8897 000020C6 31C9 <1> xor ecx, ecx 8898 000020C8 FEC5 <1> inc ch 8899 <1> ; ecx = 256 8900 000020CA FA <1> cli 8901 000020CB FC <1> cld 8902 000020CC F3666F <1> rep outsw 8903 000020CF FB <1> sti 8904 <1> 8905 <1> ; 10/07/2022 8906 <1> ;test byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT 8907 <1> ;jz short CMD_O3 8908 <1> ; 8909 <1> ;call WAIT_DRQ ; WAIT FOR DATA REQUEST 8910 <1> ;jc short TM_OUT 8911 <1> ;;mov dx, HF_PORT 8912 <1> ;mov dx, [HF_PORT] 8913 <1> ;sub ecx, ecx 8914 <1> ;;mov ecx, 4 ; mov cx, 4 ; OUTPUT THE ECC BYTES 8915 <1> ;mov cl, 4 8916 <1> ;CMD_O2: 8917 <1> ;;lodsb 8918 <1> ;mov al, [esi] 8919 <1> ;out dx, al 8920 <1> ;inc esi 8921 <1> ;loop CMD_O2 8922 <1> 8923 <1> CMD_O3: 8924 000020D0 E8D0010000 <1> call _WAIT ; WAIT FOR SECTOR COMPLETE INTERRUPT 8925 000020D5 75D5 <1> jnz short TM_OUT ; ERROR RETURNED 8926 000020D7 E8E5000000 <1> call CHECK_STATUS 8927 000020DC 75CE <1> jnz short CMD_ABORT 8928 <1> 8929 <1> ; 11/07/2022 8930 <1> ; (sector count = 1) 8931 <1> ;test byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE 8932 <1> ;jnz short CMD_O1 8933 <1> 8934 <1> ;mov dx, HF_PORT+2 ; CHECK RESIDUAL SECTOR COUNT 8935 000020DE 668B15[82620000] <1> mov dx, [HF_PORT] 8936 000020E5 80C202 <1> add dl, 2 8937 <1> ;inc dl 8938 <1> ;inc dl 8939 000020E8 EC <1> in al, dx ; 8940 000020E9 A8FF <1> test al, 0FFh ; 8941 000020EB 7407 <1> jz short CMD_O4 ; COUNT = 0 OK 8942 000020ED C605[FB670000]BB <1> mov byte [DISK_STATUS1], UNDEF_ERR 8943 <1> ; OPERATION ABORTED - PARTIAL TRANSFER 8944 <1> CMD_O4: 8945 000020F4 C3 <1> retn 8946 <1> 8947 <1> ; 10/07/2022 8948 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 8949 <1> 8950 <1> ;---------------------------------------- 8951 <1> ; RESET THE DISK SYSTEM (AH=00H) : 8952 <1> ;---------------------------------------- 8953 <1> 8954 <1> ; 18-1-2015 : one controller reset (not other one) 8955 <1> 8956 <1> DISK_RESET: 8957 000020F5 FA <1> cli 8958 000020F6 E4A1 <1> in al, INTB01 ; GET THE MASK REGISTER 8959 <1> ;JMP $+2 8960 <1> IODELAY 8961 000020F8 EB00 <2> jmp short $+2 8962 000020FA EB00 <2> jmp short $+2 8963 <1> ;and al, 0BFh ; ENABLE FIXED DISK INTERRUPT 8964 000020FC 243F <1> and al, 3Fh ; 22/12/2014 (IRQ 14 & IRQ 15) 8965 000020FE E6A1 <1> out INTB01, al 8966 00002100 FB <1> sti ; START INTERRUPTS 8967 <1> ; 14/02/2015 8968 <1> ;mov di, dx 8969 <1> ; 24/12/2021 8970 00002101 89D7 <1> mov edi, edx 8971 <1> ; 04/01/2015 8972 <1> ;xor di,di 8973 <1> drst0: 8974 00002103 B004 <1> mov al, 04h ; bit 2 - SRST 8975 <1> ;mov dx, HF_REG_PORT 8976 00002105 668B15[84620000] <1> mov dx, [HF_REG_PORT] 8977 0000210C EE <1> out dx, al ; RESET 8978 <1> ; mov cx, 10 ; DELAY COUNT 8979 <1> ;DRD: dec cx 8980 <1> ; jnz short DRD ; WAIT 4.8 MICRO-SEC 8981 <1> ;mov cx, 2 ; wait for 30 micro seconds 8982 <1> ;mov ecx, 2 ; 21/02/2015 8983 <1> ; 10/07/2022 8984 0000210D 29C9 <1> sub ecx, ecx 8985 0000210F B102 <1> mov cl, 2 8986 00002111 E895F2FFFF <1> call WAITF ; (Award Bios 1999 - WAIT_REFRESH, 8987 <1> ; 40 micro seconds) 8988 00002116 A0[FD670000] <1> mov al, [CONTROL_BYTE] 8989 0000211B 240F <1> and al, 0Fh ; SET HEAD OPTION 8990 0000211D EE <1> out dx, al ; TURN RESET OFF 8991 0000211E E8B2010000 <1> call NOT_BUSY 8992 00002123 7514 <1> jnz short DRERR ; TIME OUT ON RESET 8993 00002125 668B15[82620000] <1> mov dx, [HF_PORT] 8994 0000212C FEC2 <1> inc dl ; HF_PORT+1 8995 <1> ; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM 8996 <1> ;mov cl, 10 8997 <1> ;mov ecx, 10 ; 21/02/2015 8998 <1> ; 10/07/2022 8999 <1> ;xor ecx, ecx 9000 0000212E B10A <1> mov cl, 10 9001 <1> drst1: 9002 00002130 EC <1> in al, dx ; GET RESET STATUS 9003 00002131 3C01 <1> cmp al, 1 9004 <1> ; 04/01/2015 9005 00002133 740C <1> jz short drst2 9006 <1> ;jnz short DRERR ; BAD RESET STATUS 9007 <1> ; Drive/Head Register - bit 4 9008 <1> ;loop drst1 9009 <1> ; 10/07/2022 9010 00002135 FEC9 <1> dec cl 9011 00002137 75F7 <1> jnz short drst1 9012 <1> DRERR: 9013 00002139 C605[FB670000]05 <1> mov byte [DISK_STATUS1], BAD_RESET ; CARD FAILED 9014 00002140 C3 <1> retn 9015 <1> drst2: 9016 <1> ; 14/02/2015 9017 <1> ;mov dx, di 9018 <1> ; 24/12/2021 9019 00002141 89FA <1> mov edx, edi 9020 <1> ;drst3: 9021 <1> ; ; 05/01/2015 9022 <1> ; shl di, 1 9023 <1> ; ; 04/01/2015 9024 <1> ; mov ax, [di+hd_cports] 9025 <1> ; cmp ax, [HF_REG_PORT] 9026 <1> ; je short drst4 9027 <1> ; mov [HF_REG_PORT], ax 9028 <1> ; ; 03/01/2015 9029 <1> ; mov ax, [di+hd_ports] 9030 <1> ; mov [HF_PORT], ax 9031 <1> ; ; 05/01/2014 9032 <1> ; shr di, 1 9033 <1> ; ; 04/01/2015 9034 <1> ; jmp short drst0 ; reset other controller 9035 <1> ;drst4: 9036 <1> ; ; 05/01/2015 9037 <1> ; shr di, 1 9038 <1> ; mov al, [di+hd_dregs] 9039 <1> ; and al, 10h ; bit 4 only 9040 <1> ; shr al, 4 ; bit 4 -> bit 0 9041 <1> ; mov [hf_m_s], al ; (0 = master, 1 = slave) 9042 <1> ; 9043 00002143 A0[86620000] <1> mov al, [hf_m_s] ; 18/01/2015 9044 00002148 A801 <1> test al, 1 9045 <1> ;jnz short drst6 9046 0000214A 7516 <1> jnz short drst4 9047 0000214C 8065FDEF <1> and byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0 9048 <1> ;drst5: 9049 <1> drst3: 9050 00002150 E813000000 <1> call INIT_DRV ; SET MAX HEADS 9051 <1> ;mov dx, di 9052 00002155 E8A3000000 <1> call HDISK_RECAL ; RECAL TO RESET SEEK SPEED 9053 <1> ; 04/01/2014 9054 <1> ; inc di 9055 <1> ; mov dx, di 9056 <1> ; cmp dl, [HF_NUM] 9057 <1> ; jb short drst3 9058 <1> ;DRE: 9059 0000215A C605[FB670000]00 <1> mov byte [DISK_STATUS1], 0 ; IGNORE ANY SET UP ERRORS 9060 00002161 C3 <1> retn 9061 <1> ;drst6: 9062 <1> drst4: ; Drive/Head Register - bit 4 9063 00002162 804DFD10 <1> or byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1 9064 <1> ;jmp short drst5 9065 00002166 EBE8 <1> jmp short drst3 9066 <1> 9067 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9068 <1> 9069 <1> ;---------------------------------------- 9070 <1> ; INITIALIZE DRIVE (AH = 09H) : 9071 <1> ;---------------------------------------- 9072 <1> ; 03/01/2015 9073 <1> ; According to ATA-ATAPI specification v2.0 to v5.0 9074 <1> ; logical sector per logical track 9075 <1> ; and logical heads - 1 would be set but 9076 <1> ; it is seen as it will be good 9077 <1> ; if physical parameters will be set here 9078 <1> ; because, number of heads <= 16. 9079 <1> ; (logical heads usually more than 16) 9080 <1> ; NOTE: ATA logical parameters (software C, H, S) 9081 <1> ; == INT 13h physical parameters 9082 <1> 9083 <1> ;INIT_DRV: 9084 <1> ; mov byte [CMD_BLOCK+6], SET_PARM_CMD 9085 <1> ; call GET_VEC ; ES:BX -> PARAMETER BLOCK 9086 <1> ; mov al, [es:bx+2] ; GET NUMBER OF HEADS 9087 <1> ; dec al ; CONVERT TO 0-INDEX 9088 <1> ; mov ah, [CMD_BLOCK+5] ; GET SDH REGISTER 9089 <1> ; and ah, 0F0h ; CHANGE HEAD NUMBER 9090 <1> ; or ah, al ; TO MAX HEAD 9091 <1> ; mov [CMD_BLOCK+5], ah 9092 <1> ; mov al, [es:bx+14] ; MAX SECTOR NUMBER 9093 <1> ; mov [CMD_BLOCK+1], al 9094 <1> ; sub ax, ax 9095 <1> ; mov [CMD_BLOCK+3], al ; ZERO FLAGS 9096 <1> ; call COMMAND ; TELL CONTROLLER 9097 <1> ; jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 9098 <1> ; call NOT_BUSY ; WAIT FOR IT TO BE DONE 9099 <1> ; jnz short INIT_EXIT ; TIME OUT 9100 <1> ; call CHECK_STATUS 9101 <1> ;INIT_EXIT: 9102 <1> ; retn 9103 <1> 9104 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9105 <1> 9106 <1> ; 04/01/2015 9107 <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999 9108 <1> ; AHDSK.ASM - INIT_DRIVE 9109 <1> INIT_DRV: 9110 <1> ;xor ah, ah 9111 00002168 31C0 <1> xor eax, eax ; 21/02/2015 9112 0000216A B00B <1> mov al, 11 ; Physical heads from translated HDPT 9113 0000216C 3825[10680000] <1> cmp [LBAMode], ah ; 0 9114 00002172 7702 <1> ja short idrv0 9115 00002174 B002 <1> mov al, 2 ; Physical heads from standard HDPT 9116 <1> idrv0: 9117 <1> ; DL = drive number (0 based) 9118 00002176 E80D020000 <1> call GET_VEC 9119 <1> ;push bx 9120 0000217B 53 <1> push ebx ; 21/02/2015 9121 <1> ;add bx, ax 9122 0000217C 01C3 <1> add ebx, eax 9123 <1> ;; 05/01/2015 9124 0000217E 8A25[86620000] <1> mov ah, [hf_m_s] ; drive number (0= master, 1= slave) 9125 <1> ;;and ah, 1 9126 00002184 C0E404 <1> shl ah, 4 9127 00002187 80CCA0 <1> or ah, 0A0h ; Drive/Head register - 10100000b (A0h) 9128 <1> ;mov al, [es:bx] 9129 0000218A 8A03 <1> mov al, [ebx] ; 21/02/2015 9130 0000218C FEC8 <1> dec al ; last head number 9131 <1> ;and al, 0Fh 9132 0000218E 08E0 <1> or al, ah ; lower 4 bits for head number 9133 <1> ; 9134 00002190 C645FE91 <1> mov byte [CMD_BLOCK+6], SET_PARM_CMD 9135 00002194 8845FD <1> mov [CMD_BLOCK+5], al 9136 <1> ;pop bx 9137 00002197 5B <1> pop ebx 9138 00002198 29C0 <1> sub eax, eax ; 21/02/2015 9139 0000219A B004 <1> mov al, 4 ; Physical sec per track from translated HDPT 9140 0000219C 803D[10680000]00 <1> cmp byte [LBAMode], 0 9141 000021A3 7702 <1> ja short idrv1 9142 000021A5 B00E <1> mov al, 14 ; Physical sec per track from standard HDPT 9143 <1> idrv1: 9144 <1> ;xor ah, ah 9145 <1> ;add bx, ax 9146 000021A7 01C3 <1> add ebx, eax ; 21/02/2015 9147 <1> ;mov al, [es:bx] 9148 <1> ; sector number 9149 000021A9 8A03 <1> mov al, [ebx] 9150 000021AB 8845F9 <1> mov [CMD_BLOCK+1], al 9151 000021AE 28C0 <1> sub al, al 9152 000021B0 8845FB <1> mov [CMD_BLOCK+3], al ; ZERO FLAGS 9153 000021B3 E87B000000 <1> call COMMAND ; TELL CONTROLLER 9154 000021B8 751E <1> jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 9155 000021BA E816010000 <1> call NOT_BUSY ; WAIT FOR IT TO BE DONE 9156 000021BF 7517 <1> jnz short INIT_EXIT ; TIME OUT 9157 <1> ;call CHECK_STATUS 9158 <1> ;jmp short CHECK_STATUS 9159 <1> ;INIT_EXIT: 9160 <1> ;retn 9161 <1> 9162 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9163 <1> 9164 <1> ;---------------------------------------- 9165 <1> ; CHECK FIXED DISK STATUS : 9166 <1> ;---------------------------------------- 9167 <1> CHECK_STATUS: 9168 000021C1 E861010000 <1> call CHECK_ST ; CHECK THE STATUS BYTE 9169 <1> ;jnz short CHECK_S1 ; AN ERROR WAS FOUND 9170 <1> ; 10/07/2022 9171 000021C6 7510 <1> jnz short CHECK_S2 9172 000021C8 A801 <1> test al, ST_ERROR ; WERE THERE ANY OTHER ERRORS 9173 000021CA 7405 <1> jz short CHECK_S1 ; NO ERROR REPORTED 9174 000021CC E894010000 <1> call CHECK_ER ; ERROR REPORTED 9175 <1> CHECK_S1: 9176 000021D1 803D[FB670000]00 <1> cmp byte [DISK_STATUS1], 0 ; SET STATUS FOR CALLER 9177 <1> CHECK_S2: 9178 <1> INIT_EXIT: ; 10/07/2022 9179 000021D8 C3 <1> retn 9180 <1> 9181 <1> ;---------------------------------------- 9182 <1> ; TEST DISK READY (AH = 10H) : 9183 <1> ;---------------------------------------- 9184 <1> 9185 <1> TST_RDY: ; WAIT FOR CONTROLLER 9186 000021D9 E8F7000000 <1> call NOT_BUSY 9187 000021DE 751C <1> jnz short TR_EX 9188 000021E0 8A45FD <1> mov al, [CMD_BLOCK+5] ; SELECT DRIVE 9189 000021E3 668B15[82620000] <1> mov dx, [HF_PORT] 9190 000021EA 80C206 <1> add dl, 6 9191 000021ED EE <1> out dx, al 9192 000021EE E834010000 <1> call CHECK_ST ; CHECK STATUS ONLY 9193 000021F3 7507 <1> jnz short TR_EX 9194 000021F5 C605[FB670000]00 <1> mov byte [DISK_STATUS1], 0 ; WIPE OUT DATA CORRECTED ERROR 9195 <1> TR_EX: 9196 000021FC C3 <1> retn 9197 <1> 9198 <1> ;---------------------------------------- 9199 <1> ; RECALIBRATE (AH = 11H) : 9200 <1> ;---------------------------------------- 9201 <1> 9202 <1> HDISK_RECAL: 9203 000021FD C645FE10 <1> mov byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16 9204 00002201 E82D000000 <1> call COMMAND ; START THE OPERATION 9205 00002206 7523 <1> jnz short RECAL_EXIT ; ERROR 9206 00002208 E898000000 <1> call _WAIT ; WAIT FOR COMPLETION 9207 0000220D 7407 <1> jz short RECAL_X ; TIME OUT ONE OK ? 9208 0000220F E891000000 <1> call _WAIT ; WAIT FOR COMPLETION LONGER 9209 00002214 7515 <1> jnz short RECAL_EXIT ; TIME OUT TWO TIMES IS ERROR 9210 <1> RECAL_X: 9211 00002216 E8A6FFFFFF <1> call CHECK_STATUS 9212 0000221B 803D[FB670000]40 <1> cmp byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE 9213 00002222 7507 <1> jne short RECAL_EXIT ; IS OK 9214 00002224 C605[FB670000]00 <1> mov byte [DISK_STATUS1], 0 9215 <1> RECAL_EXIT: 9216 0000222B 803D[FB670000]00 <1> cmp byte [DISK_STATUS1], 0 9217 00002232 C3 <1> retn 9218 <1> 9219 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9220 <1> 9221 <1> ;-------------------------------------------------------- 9222 <1> ; COMMAND : 9223 <1> ; THIS ROUTINE OUTPUTS THE COMMAND BLOCK : 9224 <1> ; OUTPUT : 9225 <1> ; BL = STATUS : 9226 <1> ; BH = ERROR REGISTER : 9227 <1> ;-------------------------------------------------------- 9228 <1> 9229 <1> COMMAND: 9230 <1> ;push ebx ; 10/07/2022 ; WAIT FOR SEEK COMPLETE AND READY 9231 <1> ;;mov ecx, DELAY_2 ; SET INITIAL DELAY BEFORE TEST 9232 <1> COMMAND1: 9233 <1> ;;push ecx ; SAVE LOOP COUNT 9234 00002233 E8A1FFFFFF <1> call TST_RDY ; CHECK DRIVE READY 9235 <1> ;;pop ecx 9236 <1> ;pop ebx ; 10/07/2022 9237 00002238 7418 <1> jz short COMMAND2 ; DRIVE IS READY 9238 0000223A 803D[FB670000]80 <1> cmp byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP 9239 <1> ;jz short CMD_TIMEOUT 9240 <1> ;;loop COMMAND1 ; KEEP TRYING FOR A WHILE 9241 <1> ;jmp short COMMAND4 ; ITS NOT GOING TO GET READY 9242 00002241 7507 <1> jne short COMMAND4 9243 <1> CMD_TIMEOUT: 9244 00002243 C605[FB670000]20 <1> mov byte [DISK_STATUS1], BAD_CNTLR 9245 <1> COMMAND4: 9246 <1> ;;pop ebx ; 10/07/2022 9247 0000224A 803D[FB670000]00 <1> cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 9248 00002251 C3 <1> retn 9249 <1> COMMAND2: 9250 <1> ;;pop ebx ; 10/07/2022 9251 <1> ;push edi ; 10/07/2022 9252 00002252 C605[F6670000]00 <1> mov byte [HF_INT_FLAG], 0 ; RESET INTERRUPT FLAG 9253 00002259 FA <1> cli ; INHIBIT INTERRUPTS WHILE CHANGING MASK 9254 0000225A E4A1 <1> in al, INTB01 ; TURN ON SECOND INTERRUPT CHIP 9255 <1> ;and al, 0BFh 9256 0000225C 243F <1> and al, 3Fh ; Enable IRQ 14 & 15 9257 <1> ;JMP $+2 9258 <1> IODELAY 9259 0000225E EB00 <2> jmp short $+2 9260 00002260 EB00 <2> jmp short $+2 9261 00002262 E6A1 <1> out INTB01, al 9262 00002264 E421 <1> in al, INTA01 ; LET INTERRUPTS PASS THRU TO 9263 00002266 24FB <1> and al, 0FBh ; SECOND CHIP 9264 <1> ;JMP $+2 9265 <1> IODELAY 9266 00002268 EB00 <2> jmp short $+2 9267 0000226A EB00 <2> jmp short $+2 9268 0000226C E621 <1> out INTA01, al 9269 0000226E FB <1> sti 9270 <1> ;xor edi, edi ; INDEX THE COMMAND TABLE 9271 <1> ; 10/07/2022 9272 0000226F 31C9 <1> xor ecx, ecx 9273 <1> ;mov dx, HF_PORT+1 ; DISK ADDRESS 9274 00002271 668B15[82620000] <1> mov dx, [HF_PORT] 9275 00002278 FEC2 <1> inc dl 9276 0000227A F605[FD670000]C0 <1> test byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION 9277 00002281 7411 <1> jz short COMMAND3 9278 00002283 8A45FE <1> mov al, [CMD_BLOCK+6] ; YES-GET OPERATION CODE 9279 00002286 24F0 <1> and al, 0F0h ; GET RID OF MODIFIERS 9280 00002288 3C20 <1> cmp al, 20h ; 20H-40H IS READ, WRITE, VERIFY 9281 0000228A 7208 <1> jb short COMMAND3 9282 0000228C 3C40 <1> cmp al, 40h 9283 0000228E 7704 <1> ja short COMMAND3 9284 00002290 804DFE01 <1> or byte [CMD_BLOCK+6], NO_RETRIES 9285 <1> ; VALID OPERATION FOR RETRY SUPPRESS 9286 <1> COMMAND3: 9287 <1> ;mov al, [CMD_BLOCK+edi] ; GET THE COMMAND STRING BYTE 9288 <1> ; 10/07/2022 9289 00002294 8A440DF8 <1> mov al, [CMD_BLOCK+ecx] 9290 00002298 EE <1> out dx, al ; GIVE IT TO CONTROLLER 9291 <1> IODELAY 9292 00002299 EB00 <2> jmp short $+2 9293 0000229B EB00 <2> jmp short $+2 9294 <1> ;inc edi ; NEXT BYTE IN COMMAND BLOCK 9295 <1> ; 10/07/2022 9296 0000229D 41 <1> inc ecx 9297 <1> ;inc dx ; NEXT DISK ADAPTER REGISTER 9298 0000229E 42 <1> inc edx ; 10/07/2022 9299 <1> ;cmp di, 7 ; 01/01/2015 ; ALL DONE? 9300 <1> ;jne short COMMAND3 ; NO--GO DO NEXT ONE 9301 0000229F 80F907 <1> cmp cl, 7 ; 10/07/2022 9302 000022A2 72F0 <1> jb short COMMAND3 9303 <1> ;pop edi ; 10/07/2022 9304 000022A4 C3 <1> retn ; ZERO FLAG IS SET 9305 <1> 9306 <1> ;CMD_TIMEOUT: 9307 <1> ; mov byte [DISK_STATUS1], BAD_CNTLR 9308 <1> ;COMMAND4: 9309 <1> ; pop ebx 9310 <1> ; cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 9311 <1> ; retn 9312 <1> 9313 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9314 <1> 9315 <1> ;---------------------------------------- 9316 <1> ; WAIT FOR INTERRUPT : 9317 <1> ;---------------------------------------- 9318 <1> ;WAIT: 9319 <1> _WAIT: 9320 000022A5 FB <1> sti ; MAKE SURE INTERRUPTS ARE ON 9321 <1> ;sub cx, cx ; SET INITIAL DELAY BEFORE TEST 9322 <1> ;clc 9323 <1> ;mov ax, 9000h ; DEVICE WAIT INTERRUPT 9324 <1> ;int 15h 9325 <1> ;jc short WT2 ; DEVICE TIMED OUT 9326 <1> ;mov bl, DELAY_1 ; SET DELAY COUNT 9327 <1> 9328 <1> ;mov bl, WAIT_HDU_INT_HI 9329 <1> ;; 21/02/2015 9330 <1> ;;mov bl, WAIT_HDU_INT_HI + 1 9331 <1> ;;mov cx, WAIT_HDU_INT_LO 9332 000022A6 B915160500 <1> mov ecx, WAIT_HDU_INT_LH 9333 <1> ; (AWARD BIOS -> WAIT_FOR_MEM) 9334 <1> ;----- WAIT LOOP 9335 <1> 9336 <1> WT1: 9337 <1> ;test byte [HF_INT_FLAG], 80h ; TEST FOR INTERRUPT 9338 000022AB F605[F6670000]C0 <1> test byte [HF_INT_FLAG], 0C0h 9339 <1> ;loopz WT1 9340 000022B2 7512 <1> jnz short WT3 ; INTERRUPT--LETS GO 9341 <1> ;dec bl 9342 <1> ;jnz short WT1 ; KEEP TRYING FOR A WHILE 9343 <1> 9344 <1> WT1_hi: 9345 000022B4 E461 <1> in al, SYS1 ; 61h (PORT_B) ; wait for lo to hi 9346 000022B6 A810 <1> test al, 10h ; transition on memory 9347 000022B8 75FA <1> jnz short WT1_hi ; refresh. 9348 <1> WT1_lo: 9349 000022BA E461 <1> in al, SYS1 ; 061h (PORT_B) 9350 000022BC A810 <1> test al, 10h 9351 000022BE 74FA <1> jz short WT1_lo 9352 000022C0 E2E9 <1> loop WT1 9353 <1> ;;or bl, bl 9354 <1> ;;jz short WT2 9355 <1> ;;dec bl 9356 <1> ;;jmp short WT1 9357 <1> ;dec bl 9358 <1> ;jnz short WT1 9359 <1> WT2: 9360 <1> ; 10/07/2022 9361 <1> ;mov byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR 9362 000022C2 B080 <1> mov al, TIME_OUT 9363 000022C4 EB07 <1> jmp short WT4 9364 <1> WT3: 9365 <1> ;mov byte [DISK_STATUS1], 0 9366 <1> ;mov byte [HF_INT_FLAG], 0 9367 000022C6 28C0 <1> sub al, al ; 0 9368 000022C8 A2[F6670000] <1> mov byte [HF_INT_FLAG], al 9369 <1> WT4: 9370 <1> NB2: 9371 000022CD A2[FB670000] <1> mov byte [DISK_STATUS1], al 9372 <1> 9373 <1> ;cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 9374 000022D2 20C0 <1> and al, al 9375 <1> ; zf = 0 -> time out, zf = 1 -> ok 9376 000022D4 C3 <1> retn 9377 <1> 9378 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9379 <1> 9380 <1> ;---------------------------------------- 9381 <1> ; WAIT FOR CONTROLLER NOT BUSY : 9382 <1> ;---------------------------------------- 9383 <1> NOT_BUSY: 9384 000022D5 FB <1> sti ; MAKE SURE INTERRUPTS ARE ON 9385 <1> ;push ebx 9386 <1> ;sub cx, cx ; SET INITIAL DELAY BEFORE TEST 9387 000022D6 668B15[82620000] <1> mov dx, [HF_PORT] 9388 000022DD 80C207 <1> add dl, 7 ; Status port (HF_PORT+7) 9389 <1> ;mov bl, DELAY_1 9390 <1> ; wait for 10 seconds 9391 <1> ;mov cx, WAIT_HDU_INT_LO ; 1615h 9392 <1> ;;mov bl, WAIT_HDU_INT_HI ; 05h 9393 <1> ;mov bl, WAIT_HDU_INT_HI + 1 9394 000022E0 B915160500 <1> mov ecx, WAIT_HDU_INT_LH ; 21/02/2015 9395 <1> ; 9396 <1> ;;mov byte [wait_count], 0 ; Reset wait counter 9397 <1> NB1: 9398 000022E5 EC <1> in al, dx ; CHECK STATUS 9399 <1> ;test al, ST_BUSY 9400 000022E6 2480 <1> and al, ST_BUSY 9401 <1> ;loopnz NB1 9402 000022E8 74E3 <1> jz short NB2 ; al = 0 ; NOT BUSY--LETS GO 9403 <1> ;dec bl 9404 <1> ;jnz short NB1 ; KEEP TRYING FOR A WHILE 9405 <1> 9406 <1> NB1_hi: 9407 000022EA E461 <1> in al, SYS1 ; wait for hi to lo 9408 000022EC A810 <1> test al, 010h ; transition on memory 9409 000022EE 75FA <1> jnz short NB1_hi ; refresh. 9410 <1> NB1_lo: 9411 000022F0 E461 <1> in al, SYS1 9412 000022F2 A810 <1> test al, 010h 9413 000022F4 74FA <1> jz short NB1_lo 9414 000022F6 E2ED <1> loop NB1 9415 <1> ;dec bl 9416 <1> ;jnz short NB1 9417 <1> ; 9418 <1> ;;cmp byte [wait_count], 182 ; 10 seconds (182 timer ticks) 9419 <1> ;;jb short NB1 9420 <1> ; 9421 <1> ;mov byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR 9422 <1> ;jmp short NB3 9423 000022F8 B080 <1> mov al, TIME_OUT 9424 <1> ;NB2: 9425 000022FA EBD1 <1> jmp short NB2 ; 10/07/2022 9426 <1> 9427 <1> ; ;mov byte [DISK_STATUS1], 0 9428 <1> ;;NB3: 9429 <1> ; ;pop ebx 9430 <1> ; mov [DISK_STATUS1], al ;;; will be set after return 9431 <1> ; ;cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 9432 <1> ; or al, al ; (zf = 0 --> timeout) 9433 <1> ; retn 9434 <1> 9435 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9436 <1> 9437 <1> ;---------------------------------------- 9438 <1> ; WAIT FOR DATA REQUEST : 9439 <1> ;---------------------------------------- 9440 <1> WAIT_DRQ: 9441 <1> ;mov cx, DELAY_3 9442 <1> ;mov dx, HF_PORT+7 9443 000022FC 668B15[82620000] <1> mov dx, [HF_PORT] 9444 00002303 80C207 <1> add dl, 7 9445 <1> ;;mov bl, WAIT_HDU_DRQ_HI ; 0 9446 <1> ;mov cx, WAIT_HDU_DRQ_LO ; 1000 (30 milli seconds) 9447 <1> ; (but it is written as 2000 9448 <1> ; micro seconds in ATORGS.ASM file 9449 <1> ; of Award Bios - 1999, D1A0622) 9450 00002306 B9E8030000 <1> mov ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 9451 <1> WQ_1: 9452 0000230B EC <1> in al, dx ; GET STATUS 9453 0000230C A808 <1> test al, ST_DRQ ; WAIT FOR DRQ 9454 0000230E 7516 <1> jnz short WQ_OK 9455 <1> ;loop WQ_1 ; KEEP TRYING FOR A SHORT WHILE 9456 <1> WQ_hi: 9457 00002310 E461 <1> in al, SYS1 ; wait for hi to lo 9458 00002312 A810 <1> test al, 010h ; transition on memory 9459 00002314 75FA <1> jnz short WQ_hi ; refresh. 9460 <1> WQ_lo: 9461 00002316 E461 <1> in al, SYS1 9462 00002318 A810 <1> test al, 010h 9463 0000231A 74FA <1> jz short WQ_lo 9464 0000231C E2ED <1> loop WQ_1 9465 <1> 9466 0000231E C605[FB670000]80 <1> mov byte [DISK_STATUS1], TIME_OUT ; ERROR 9467 00002325 F9 <1> stc 9468 <1> WQ_OK: 9469 00002326 C3 <1> retn 9470 <1> ;WQ_OK: 9471 <1> ;clc 9472 <1> ;retn 9473 <1> 9474 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9475 <1> 9476 <1> ;---------------------------------------- 9477 <1> ; CHECK FIXED DISK STATUS BYTE : 9478 <1> ;---------------------------------------- 9479 <1> CHECK_ST: 9480 <1> ;mov dx, HF_PORT+7 ; GET THE STATUS 9481 00002327 668B15[82620000] <1> mov dx, [HF_PORT] 9482 0000232E 80C207 <1> add dl, 7 9483 00002331 EC <1> in al, dx 9484 00002332 A2[F5670000] <1> mov [HF_STATUS], al 9485 <1> ;mov ah, 0 9486 00002337 28E4 <1> sub ah, ah ; 0 9487 00002339 A880 <1> test al, ST_BUSY ; IF STILL BUSY 9488 0000233B 751A <1> jnz short CKST_EXIT ; REPORT OK 9489 0000233D B4CC <1> mov ah, WRITE_FAULT 9490 0000233F A820 <1> test al, ST_WRT_FLT ; CHECK FOR WRITE FAULT 9491 00002341 7514 <1> jnz short CKST_EXIT 9492 00002343 B4AA <1> mov ah, NOT_RDY 9493 00002345 A840 <1> test al, ST_READY ; CHECK FOR NOT READY 9494 00002347 740E <1> jz short CKST_EXIT 9495 00002349 B440 <1> mov ah, BAD_SEEK 9496 0000234B A810 <1> test al, ST_SEEK_COMPL ; CHECK FOR SEEK NOT COMPLETE 9497 0000234D 7408 <1> jz short CKST_EXIT 9498 0000234F B411 <1> mov ah, DATA_CORRECTED 9499 00002351 A804 <1> test al, ST_CORRCTD ; CHECK FOR CORRECTED ECC 9500 00002353 7502 <1> jnz short CKST_EXIT 9501 <1> ;mov ah, 0 9502 00002355 30E4 <1> xor ah, ah ; 0 9503 <1> CKST_EXIT: 9504 00002357 8825[FB670000] <1> mov [DISK_STATUS1], ah ; SET ERROR FLAG 9505 0000235D 80FC11 <1> cmp ah, DATA_CORRECTED ; KEEP GOING WITH DATA CORRECTED 9506 00002360 7402 <1> je short CKST_EX1 9507 <1> ;cmp ah, 0 9508 00002362 20E4 <1> and ah, ah 9509 <1> CKST_EX1: 9510 00002364 C3 <1> retn 9511 <1> 9512 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9513 <1> 9514 <1> ;---------------------------------------- 9515 <1> ; CHECK FIXED DISK ERROR REGISTER : 9516 <1> ;---------------------------------------- 9517 <1> CHECK_ER: 9518 <1> ;mov dx, HF_PORT+1 ; GET THE ERROR REGISTER 9519 00002365 668B15[82620000] <1> mov dx, [HF_PORT] ; 9520 0000236C FEC2 <1> inc dl 9521 0000236E EC <1> in al, dx 9522 <1> ; 10/07/2022 9523 <1> ;mov [HF_ERROR], al 9524 <1> ;push ebx ; 21/02/2015 9525 0000236F 29C9 <1> sub ecx, ecx 9526 <1> ;mov ecx, 8 ; TEST ALL 8 BITS 9527 00002371 B108 <1> mov cl, 8 9528 <1> CK1: 9529 00002373 D0E0 <1> shl al, 1 ; MOVE NEXT ERROR BIT TO CARRY 9530 00002375 7202 <1> jc short CK2 ; FOUND THE ERROR 9531 00002377 E2FA <1> loop CK1 ; KEEP TRYING 9532 <1> CK2: 9533 <1> ;mov ebx, ERR_TBL ; COMPUTE ADDRESS OF 9534 <1> ;add ebx, ecx ; ERROR CODE 9535 00002379 81C1[78620000] <1> add ecx, ERR_TBL ; 10/07/2022 9536 <1> 9537 <1> ;;;mov ah, byte [cs:bx] ; GET ERROR CODE 9538 <1> ;;mov ah, [bx] 9539 <1> ;mov ah, [ebx] ; 21/02/2015 9540 0000237F 8A21 <1> mov ah, [ecx] 9541 <1> CKEX: 9542 00002381 8825[FB670000] <1> mov [DISK_STATUS1], ah ; SAVE ERROR CODE 9543 <1> ; 10/07/2022 9544 <1> ;pop ebx 9545 <1> ;;cmp ah, 0 9546 <1> ;and ah, ah 9547 00002387 C3 <1> retn 9548 <1> 9549 <1> ;-------------------------------------------------------- 9550 <1> ; CHECK_DMA : 9551 <1> ; -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL : 9552 <1> ; FIT WITHOUT SEGMENT OVERFLOW. : 9553 <1> ; -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X : 9554 <1> ; -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE) : 9555 <1> ; -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H) : 9556 <1> ; -ERROR OTHERWISE : 9557 <1> ;-------------------------------------------------------- 9558 <1> 9559 <1> ; 11/07/2022 9560 <1> ; (not needed for hard disks and 32 bit OS) 9561 <1> ; 9562 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9563 <1> ;CHECK_DMA: 9564 <1> ; ;;push ax ; SAVE REGISTERS 9565 <1> ; ;; 24/12/2021 9566 <1> ; ;;push eax 9567 <1> ; ;mov ax, 8000h ; AH = MAX # SECTORS 9568 <1> ; ; AL = MAX OFFSET 9569 <1> ; ; 10/07/2022 9570 <1> ; ;test byte [CMD_BLOCK+6], ECC_MODE 9571 <1> ; ;jz short CKD1 9572 <1> ; ;mov ax, 7F04h ; ECC IS 4 MORE BYTES 9573 <1> ;CKD1: 9574 <1> ; ;cmp ah, [CMD_BLOCK+1] ; NUMBER OF SECTORS 9575 <1> ; ;ja short CKDOK ; IT WILL FIT 9576 <1> ; ;jb short CKDERR ; TOO MANY 9577 <1> ; 9578 <1> ; cmp byte [CMD_BLOCK+1], 80h 9579 <1> ; jb short CKDOK 9580 <1> ; ja short CKDERR 9581 <1> ; ;cmp al, bl ; CHECK OFFSET ON MAX SECTORS 9582 <1> ; ;jb short CKDERR ; ERROR 9583 <1> ;CKD2: 9584 <1> ; or bl, bl 9585 <1> ; jz short CKDR 9586 <1> ; 9587 <1> ;;CKDOK: 9588 <1> ; ;clc ; CLEAR CARRY 9589 <1> ; ;;pop ax 9590 <1> ; ;; 24/12/2021 9591 <1> ; ;pop eax 9592 <1> ; ;retn ; NORMAL RETURN 9593 <1> ;CKDERR: 9594 <1> ; stc ; INDICATE ERROR 9595 <1> ; mov byte [DISK_STATUS1], DMA_BOUNDARY 9596 <1> ; ;;pop ax 9597 <1> ; ;; 24/12/2021 9598 <1> ; ;pop eax 9599 <1> ; retn 9600 <1> ; 9601 <1> ; ; 10/07/2022 9602 <1> ;CKDOK: 9603 <1> ; clc 9604 <1> ;CKDR: 9605 <1> ; retn 9606 <1> 9607 <1> ;---------------------------------------- 9608 <1> ; SET UP EBX-> DISK PARMS : 9609 <1> ;---------------------------------------- 9610 <1> 9611 <1> ; INPUT -> DL = 0 based drive number 9612 <1> ; OUTPUT -> EBX = disk parameter table address 9613 <1> 9614 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 9615 <1> 9616 <1> GET_VEC: 9617 <1> ;sub ax, ax ; GET DISK PARAMETER ADDRESS 9618 <1> ;mov es, ax 9619 <1> ;test dl, 1 9620 <1> ;jz short GV_0 9621 <1> ; les bx, [HF1_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 9622 <1> ; jmp short GV_EXIT 9623 <1> ;GV_0: 9624 <1> ; les bx,[HF_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 9625 <1> ; 9626 00002388 31DB <1> xor ebx, ebx 9627 0000238A 88D3 <1> mov bl, dl 9628 <1> ;02/01/2015 9629 <1> ;xor bh, bh 9630 <1> ;shl bl, 1 ; port address offset 9631 <1> ;mov ax, [bx+hd_ports] ; Base port address (1F0h, 170h) 9632 <1> ;shl bl, 1 ; dpt pointer offset 9633 0000238C C0E302 <1> shl bl, 2 9634 <1> ;add bx, HF_TBL_VEC ; Disk parameter table pointer 9635 0000238F 81C3[00680000] <1> add ebx, HF_TBL_VEC ; 21/02/2015 9636 <1> ;push word [bx+2] ; dpt segment 9637 <1> ;pop es 9638 <1> ;mov bx, [bx] ; dpt offset 9639 00002395 8B1B <1> mov ebx, [ebx] 9640 <1> ;GV_EXIT: 9641 00002397 C3 <1> retn 9642 <1> 9643 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 9644 <1> hdc1_int: ; 21/02/2015 9645 <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL 14 ) ---------------------- 9646 <1> ; : 9647 <1> ; FIXED DISK INTERRUPT ROUTINE : 9648 <1> ; : 9649 <1> ;---------------------------------------------------------------- 9650 <1> 9651 <1> ; 22/12/2014 9652 <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT) 9653 <1> ; '11/15/85' 9654 <1> ; AWARD BIOS 1999 (D1A0622) 9655 <1> ; Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1) 9656 <1> 9657 <1> ;int_76h: 9658 <1> HD_INT: 9659 <1> ;push ax 9660 <1> ; 24/12/2021 9661 00002398 50 <1> push eax 9662 00002399 1E <1> push ds 9663 <1> ;CALL DDS 9664 <1> ; 21/02/2015 (32 bit, 386 pm modification) 9665 0000239A 66B81000 <1> mov ax, KDATA 9666 0000239E 8ED8 <1> mov ds, ax 9667 <1> ; 9668 <1> ;;MOV @HF_INT_FLAG, 0FFH ; ALL DONE 9669 <1> ;mov byte [CS:HF_INT_FLAG], 0FFh 9670 000023A0 C605[F6670000]FF <1> mov byte [HF_INT_FLAG], 0FFh 9671 <1> ; 9672 <1> ;push dx 9673 <1> ; 24/12/2021 9674 000023A7 52 <1> push edx 9675 000023A8 66BAF701 <1> mov dx, HDC1_BASEPORT+7 ; Status Register (1F7h) 9676 <1> ; Clear Controller 9677 <1> Clear_IRQ1415: ; (Award BIOS - 1999) 9678 000023AC EC <1> in al, dx ; 9679 <1> ;pop dx 9680 <1> ; 24/12/2021 9681 000023AD 5A <1> pop edx 9682 <1> NEWIODELAY 9683 000023AE E6EB <2> out 0EBh,al 9684 <1> ; 9685 000023B0 B020 <1> mov al, EOI ; NON-SPECIFIC END OF INTERRUPT 9686 000023B2 E6A0 <1> out INTB00, al ; FOR CONTROLLER #2 9687 <1> ;JMP $+2 ; WAIT 9688 <1> NEWIODELAY 9689 000023B4 E6EB <2> out 0EBh,al 9690 000023B6 E620 <1> out INTA00, al ; FOR CONTROLLER #1 9691 000023B8 1F <1> pop ds 9692 <1> ;sti ; RE-ENABLE INTERRUPTS 9693 <1> ;mov ax, 9100h ; DEVICE POST 9694 <1> ;int 15h ; INTERRUPT 9695 <1> irq15_iret: ; 25/02/2015 9696 <1> ;pop ax 9697 <1> ; 24/12/2021 9698 000023B9 58 <1> pop eax 9699 000023BA CF <1> iretd ; RETURN FROM INTERRUPT 9700 <1> 9701 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 9702 <1> hdc2_int: ; 21/02/2015 9703 <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL 15 ) ---------------------- 9704 <1> ; : 9705 <1> ; FIXED DISK INTERRUPT ROUTINE : 9706 <1> ; : 9707 <1> ;---------------------------------------------------------------- 9708 <1> 9709 <1> ;int_77h: 9710 <1> HD1_INT: 9711 <1> ;push ax 9712 <1> ; 24/12/2021 9713 000023BB 50 <1> push eax 9714 <1> ; Check if that is a spurious IRQ (from slave PIC) 9715 <1> ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 9716 000023BC B00B <1> mov al, 0Bh ; In-Service Register 9717 000023BE E6A0 <1> out 0A0h, al 9718 000023C0 EB00 <1> jmp short $+2 9719 000023C2 EB00 <1> jmp short $+2 9720 000023C4 E4A0 <1> in al, 0A0h 9721 000023C6 2480 <1> and al, 80h ; bit 7 (is it real IRQ 15 or fake?) 9722 000023C8 74EF <1> jz short irq15_iret ; Fake (spurious)IRQ, do not send EOI) 9723 <1> ; 9724 000023CA 1E <1> push ds 9725 <1> ;CALL DDS 9726 <1> ; 21/02/2015 (32 bit, 386 pm modification) 9727 000023CB 66B81000 <1> mov ax, KDATA 9728 000023CF 8ED8 <1> mov ds, ax 9729 <1> ; 9730 <1> ;;MOV @HF_INT_FLAG,0FFH ; ALL DONE 9731 <1> ;or byte [CS:HF_INT_FLAG], 0C0h 9732 000023D1 800D[F6670000]C0 <1> or byte [HF_INT_FLAG], 0C0h 9733 <1> ; 9734 <1> ;push dx 9735 <1> ; 24/12/2021 9736 000023D8 52 <1> push edx 9737 000023D9 66BA7701 <1> mov dx, HDC2_BASEPORT+7 ; Status Register (177h) 9738 <1> ; Clear Controller (Award BIOS 1999) 9739 000023DD EBCD <1> jmp short Clear_IRQ1415 9740 <1> 9741 <1> ;%include 'diskdata.inc' ; 11/03/2015 9742 <1> ;%include 'diskbss.inc' ; 11/03/2015 9743 <1> 9744 <1> ;//////////////////////////////////////////////////////////////////// 9745 <1> ;; END OF DISK I/O SYTEM /// 9746 %include 'memory.s' ; 09/03/2015 9747 <1> ; Retro UNIX 386 v2 - memory.s - 26/01/2020 9748 <1> ; Last Modification: 17/07/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.3) 9749 <1> ; ---------------------------------------------------------------------------- 9750 <1> ; 9751 <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) 9752 <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC 9753 <1> ; 18/10/2015 (!not completed!) 9754 <1> ; 9755 <1> ; Source code for NASM - Netwide Assembler (2.11) 9756 <1> 9757 <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) /////////////// 9758 <1> 9759 <1> ;;04/11/2014 (unix386.s) 9760 <1> ;PDE_A_PRESENT equ 1 ; Present flag for PDE 9761 <1> ;PDE_A_WRITE equ 2 ; Writable (write permission) flag 9762 <1> ;PDE_A_USER equ 4 ; User (non-system/kernel) page flag 9763 <1> ;; 9764 <1> ;PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 9765 <1> ;PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 9766 <1> ;PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 9767 <1> ;PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 9768 <1> 9769 <1> ; 27/04/2015 9770 <1> ; 09/03/2015 9771 <1> PAGE_SIZE equ 4096 ; page size in bytes 9772 <1> PAGE_SHIFT equ 12 ; page table shift count 9773 <1> PAGE_D_SHIFT equ 22 ; 12+10 ; page directory shift count 9774 <1> PAGE_OFF equ 0FFFh ; 12 bit byte offset in page frame 9775 <1> PTE_MASK equ 03FFh ; page table entry mask 9776 <1> PTE_DUPLICATED equ 200h ; duplicated page sign (AVL bit 0) 9777 <1> PDE_A_CLEAR equ 0F000h ; to clear PDE attribute bits 9778 <1> PTE_A_CLEAR equ 0F000h ; to clear PTE attribute bits 9779 <1> LOGIC_SECT_SIZE equ 512 ; logical sector size 9780 <1> ERR_MAJOR_PF equ 0E0h ; major error: page fault 9781 <1> ; 15/10/2016 (TRDOS 386 v2) 9782 <1> ERR_MINOR_IM equ 4 ;15/10/2016 (1->4); insufficient (out of) memory 9783 <1> ERR_MINOR_PV equ 6 ;15/10/2016 (3->6); protection violation 9784 <1> SWP_DISK_READ_ERR equ 40 9785 <1> SWP_DISK_NOT_PRESENT_ERR equ 41 9786 <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42 9787 <1> SWP_NO_FREE_SPACE_ERR equ 43 9788 <1> SWP_DISK_WRITE_ERR equ 44 9789 <1> SWP_NO_PAGE_TO_SWAP_ERR equ 45 9790 <1> PTE_A_ACCESS_BIT equ 5 ; Bit 5 (accessed flag) 9791 <1> SECTOR_SHIFT equ 3 ; sector shift (to convert page block number) 9792 <1> ; 10/06/2021 (Retro UNIX 386 v2) 9793 <1> ; 12/07/2016 (TRDOS 386 v2) 9794 <1> PTE_SHARED equ 400h ; AVL bit 1, direct memory access bit 9795 <1> ; (Indicates that the page is not allocated 9796 <1> ; for the process, it is a shared or system 9797 <1> ; page, it must not be deallocated!) 9798 <1> ; 14/12/2020 9799 <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.) 9800 <1> PDE_EXTERNAL equ 400h ; Page directory entry for external memory blocks 9801 <1> PTE_EXTERNAL equ 400h ; Allocated kernel pages for Linear Frame Buffer 9802 <1> ; (Out of memory allocation table) 9803 <1> ; 9804 <1> ;; Retro Unix 386 v1 - paging method/principles 9805 <1> ;; 9806 <1> ;; 10/10/2014 9807 <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES 9808 <1> ;; 9809 <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map 9810 <1> ;; (virtual address = physical address) 9811 <1> ;; KERNEL PAGE TABLES: 9812 <1> ;; Kernel page directory and all page tables are 9813 <1> ;; on memory as initialized, as equal to physical memory 9814 <1> ;; layout. Kernel pages can/must not be swapped out/in. 9815 <1> ;; 9816 <1> ;; what for: User pages may be swapped out, when accessing 9817 <1> ;; a page in kernel/system mode, if it would be swapped out, 9818 <1> ;; kernel would have to swap it in! But it is also may be 9819 <1> ;; in use by a user process. (In system/kernel mode 9820 <1> ;; kernel can access all memory pages even if they are 9821 <1> ;; reserved/allocated for user processes. Swap out/in would 9822 <1> ;; cause conflicts.) 9823 <1> ;; 9824 <1> ;; As result of these conditions, 9825 <1> ;; all kernel pages must be initialized as equal to 9826 <1> ;; physical layout for preventing page faults. 9827 <1> ;; Also, calling "allocate page" procedure after 9828 <1> ;; a page fault can cause another page fault (double fault) 9829 <1> ;; if all kernel page tables would not be initialized. 9830 <1> ;; 9831 <1> ;; [first_page] = Beginning of users space, as offset to 9832 <1> ;; memory allocation table. (double word aligned) 9833 <1> ;; 9834 <1> ;; [next_page] = first/next free space to be searched 9835 <1> ;; as offset to memory allocation table. (dw aligned) 9836 <1> ;; 9837 <1> ;; [last_page] = End of memory (users space), as offset 9838 <1> ;; to memory allocation table. (double word aligned) 9839 <1> ;; 9840 <1> ;; USER PAGE TABLES: 9841 <1> ;; Demand paging (& 'copy on write' allocation method) ... 9842 <1> ;; 'ready only' marked copies of the 9843 <1> ;; parent process's page table entries (for 9844 <1> ;; same physical memory). 9845 <1> ;; (A page will be copied to a new page after 9846 <1> ;; if it causes R/W page fault.) 9847 <1> ;; 9848 <1> ;; Every user process has own (different) 9849 <1> ;; page directory and page tables. 9850 <1> ;; 9851 <1> ;; Code starts at virtual address 0, always. 9852 <1> ;; (Initial value of EIP is 0 in user mode.) 9853 <1> ;; (Programs can be written/developed as simple 9854 <1> ;; flat memory programs.) 9855 <1> ;; 9856 <1> ;; MEMORY ALLOCATION STRATEGY: 9857 <1> ;; Memory page will be allocated by kernel only 9858 <1> ;; (in kernel/system mode only). 9859 <1> ;; * After a 9860 <1> ;; - 'not present' page fault 9861 <1> ;; - 'writing attempt on read only page' page fault 9862 <1> ;; * For loading (opening, reading) a file or disk/drive 9863 <1> ;; * As responce to 'allocate additional memory blocks' 9864 <1> ;; request by running process. 9865 <1> ;; * While creating a process, allocating a new buffer, 9866 <1> ;; new page tables etc. 9867 <1> ;; 9868 <1> ;; At first, 9869 <1> ;; - 'allocate page' procedure will be called; 9870 <1> ;, if it will return with a valid (>0) physical address 9871 <1> ;; (that means the relevant M.A.T. bit has been RESET) 9872 <1> ;; relevant memory page/block will be cleared (zeroed). 9873 <1> ;; - 'allocate page' will be called for allocating page 9874 <1> ;; directory, page table and running space (data/code). 9875 <1> ;; - every successful 'allocate page' call will decrease 9876 <1> ;; 'free_pages' count (pointer). 9877 <1> ;; - 'out of (insufficient) memory error' will be returned 9878 <1> ;; if 'free_pages' points to a ZERO. 9879 <1> ;; - swapping out and swapping in (if it is not a new page) 9880 <1> ;; procedures will be called as responce to 'out of memory' 9881 <1> ;; error except errors caused by attribute conflicts. 9882 <1> ;; (swapper functions) 9883 <1> ;; 9884 <1> ;; At second, 9885 <1> ;; - page directory entry will be updated then page table 9886 <1> ;; entry will be updated. 9887 <1> ;; 9888 <1> ;; MEMORY ALLOCATION TABLE FORMAT: 9889 <1> ;; - M.A.T. has a size according to available memory as 9890 <1> ;; follows: 9891 <1> ;; - 1 (allocation) bit per 1 page (4096 bytes) 9892 <1> ;; - a bit with value of 0 means allocated page 9893 <1> ;; - a bit with value of 1 means a free page 9894 <1> ;, - 'free_pages' pointer holds count of free pages 9895 <1> ;; depending on M.A.T. 9896 <1> ;; (NOTE: Free page count will not be checked 9897 <1> ;; again -on M.A.T.- after initialization. 9898 <1> ;; Kernel will trust on initial count.) 9899 <1> ;, - 'free_pages' count will be decreased by allocation 9900 <1> ;; and it will be increased by deallocation procedures. 9901 <1> ;; 9902 <1> ;; - Available memory will be calculated during 9903 <1> ;; the kernel's initialization stage (in real mode). 9904 <1> ;; Memory allocation table and kernel page tables 9905 <1> ;; will be formatted/sized as result of available 9906 <1> ;; memory calculation before paging is enabled. 9907 <1> ;; 9908 <1> ;; For 4GB Available/Present Memory: (max. possible memory size) 9909 <1> ;; - Memory Allocation Table size will be 128 KB. 9910 <1> ;; - Memory allocation for kernel page directory size 9911 <1> ;; is always 4 KB. (in addition to total allocation size 9912 <1> ;; for page tables) 9913 <1> ;; - Memory allocation for kernel page tables (1024 tables) 9914 <1> ;; is 4 MB (1024*4*1024 bytes). 9915 <1> ;; - User (available) space will be started 9916 <1> ;; at 6th MB of the memory (after 1MB+4MB). 9917 <1> ;; - The first 640 KB is for kernel's itself plus 9918 <1> ;; memory allocation table and kernel's page directory 9919 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 9920 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 9921 <1> ;; for buffers. 9922 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 9923 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 9924 <1> ;; - Kernel page tables start at 100000h (2nd MB) 9925 <1> ;; 9926 <1> ;; For 1GB Available Memory: 9927 <1> ;; - Memory Allocation Table size will be 32 KB. 9928 <1> ;; - Memory allocation for kernel page directory size 9929 <1> ;; is always 4 KB. (in addition to total allocation size 9930 <1> ;; for page tables) 9931 <1> ;; - Memory allocation for kernel page tables (256 tables) 9932 <1> ;; is 1 MB (256*4*1024 bytes). 9933 <1> ;; - User (available) space will be started 9934 <1> ;; at 3th MB of the memory (after 1MB+1MB). 9935 <1> ;; - The first 640 KB is for kernel's itself plus 9936 <1> ;; memory allocation table and kernel's page directory 9937 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 9938 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 9939 <1> ;; for buffers. 9940 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 9941 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 9942 <1> ;; - Kernel page tables start at 100000h (2nd MB). 9943 <1> ;; 9944 <1> ;; 9945 <1> 9946 <1> ;;************************************************************************************ 9947 <1> ;; 9948 <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle) 9949 <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015) 9950 <1> 9951 <1> ;; Main factor: "sys fork" system call 9952 <1> ;; 9953 <1> ;; FORK 9954 <1> ;; |----> parent - duplicated PTEs, read only pages 9955 <1> ;; writable pages ---->| 9956 <1> ;; |----> child - duplicated PTEs, read only pages 9957 <1> ;; 9958 <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 9959 <1> ;; 9960 <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set) 9961 <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9) 9962 <1> ;; -while R/W bit is 0-. 9963 <1> ;; 9964 <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process): 9965 <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 9966 <1> ;; as duplicated PTE bit -AVL bit 0, PTE bit 9- are reset/clear. 9967 <1> ;; # Then Parent's Page Table is copied to Child's Page Table. 9968 <1> ;; # Child's Page Table Entries are updated as duplicated child bit 9969 <1> ;; -AVL bit 0, PTE bit 9- is set. 9970 <1> ;; 9971 <1> ;; Duplicate page tables with read only pages (several sys fork system calls): 9972 <1> ;; # Parent's read only pages are copied to new child pages. 9973 <1> ;; Parent's PTE attributes are not changed. 9974 <1> ;; (Because, there is another parent-child fork before this fork! We must not 9975 <1> ;; destroy/mix previous fork result). 9976 <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 9977 <1> ;; read only pages) are set as writable (while duplicated PTE bit is clear). 9978 <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 9979 <1> ;; as read only, (while) duplicated PTE bit is reset (clear). 9980 <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 9981 <1> ;; as Child's Page Table Entries without copying actual page. 9982 <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 9983 <1> ;; pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set. 9984 <1> ;; 9985 <1> ;; !? WHAT FOR (duplication after duplication): 9986 <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init) 9987 <1> ;; program/executable code continues from specified location as child process, 9988 <1> ;; returns back previous code location as parent process, every child after 9989 <1> ;; every sys fork uses last image of code and data just prior the fork. 9990 <1> ;; Even if the parent code changes data, the child will not see the changed data 9991 <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB) 9992 <1> ;; was copied to child's process segment (all of code and data) according to 9993 <1> ;; original UNIX v1 which copies all of parent process code and data -core- 9994 <1> ;; to child space -core- but swaps that core image -of child- on to disk. 9995 <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core 9996 <1> ;; (complete running image of parent process) to the child process; 9997 <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 9998 <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork, 9999 <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes 10000 <1> ;; a new/fresh core -running space-, by clearing all code/data content). 10001 <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write 10002 <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 10003 <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and 10004 <1> ;; new/fresh pages will be used to load and run new executable/program. 10005 <1> ;; That is what for i have preferred "copy on write", "duplication" method 10006 <1> ;; for sharing same read only pages between parent and child processes. 10007 <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 10008 <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 10009 <1> ;; and it's child processes; otherwise parent process would destroy data belongs 10010 <1> ;; to its child or vice versa; or some pages would remain unclaimed 10011 <1> ;; -deallocation problem-. 10012 <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 10013 <1> ;; 10014 <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 10015 <1> ;; # Page fault handler will do those: 10016 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 10017 <1> ;; - If it is reset/clear, there is a child uses same page. 10018 <1> ;; - Parent's read only page -previous page- is copied to a new writable page. 10019 <1> ;; - Parent's PTE is updated as writable page, as unique page (AVL=0) 10020 <1> ;; - (Page fault handler whill check this PTE later, if child process causes to 10021 <1> ;; page fault due to write attempt on read only page. Of course, the previous 10022 <1> ;; read only page will be converted to writable and unique page which belongs 10023 <1> ;; to child process.) 10024 <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 10025 <1> ;; # Page fault handler will do those: 10026 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 10027 <1> ;; - If it is set, there is a parent uses -or was using- same page. 10028 <1> ;; - Same PTE address within parent's page table is checked if it has same page 10029 <1> ;; address or not. 10030 <1> ;; - If parent's PTE has same address, child will continue with a new writable page. 10031 <1> ;; Parent's PTE will point to same (previous) page as writable, unique (AVL=0). 10032 <1> ;; - If parent's PTE has different address, child will continue with it's 10033 <1> ;; own/same page but read only flag (0) will be changed to writable flag (1) and 10034 <1> ;; 'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 10035 <1> ;; 10036 <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables 10037 <1> ;; will be set as writable (and unique) in case of child process was using 10038 <1> ;; same pages with duplicated child PTE sign... Depending on sys fork and 10039 <1> ;; duplication method details, it is not possible multiple child processes 10040 <1> ;; were using same page with duplicated PTEs. 10041 <1> ;; 10042 <1> ;;************************************************************************************ 10043 <1> 10044 <1> ;; 08/10/2014 10045 <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft 10046 <1> ;; by Erdogan Tan (Based on KolibriOS 'memory.inc') 10047 <1> 10048 <1> ;; 'allocate_page' code is derived and modified from KolibriOS 10049 <1> ;; 'alloc_page' procedure in 'memory.inc' 10050 <1> ;; (25/08/2014, Revision: 5057) file 10051 <1> ;; by KolibriOS Team (2004-2012) 10052 <1> 10053 <1> allocate_page: 10054 <1> ; 17/04/2021 - Retro UNIX 386 v2 10055 <1> ; (temporary modifications) 10056 <1> ; 01/07/2015 10057 <1> ; 05/05/2015 10058 <1> ; 30/04/2015 10059 <1> ; 16/10/2014 10060 <1> ; 08/10/2014 10061 <1> ; 09/09/2014 (Retro UNIX 386 v1 - beginning) 10062 <1> ; 10063 <1> ; INPUT -> none 10064 <1> ; 10065 <1> ; OUTPUT -> 10066 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 10067 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is RESET) 10068 <1> ; 10069 <1> ; CF = 1 and EAX = 0 10070 <1> ; if there is not a free page to be allocated 10071 <1> ; 10072 <1> ; Modified Registers -> none (except EAX) 10073 <1> ; 10074 000023DF A1[70670000] <1> mov eax, [free_pages] 10075 000023E4 21C0 <1> and eax, eax 10076 000023E6 7438 <1> jz short out_of_memory 10077 <1> ; 10078 000023E8 53 <1> push ebx 10079 000023E9 51 <1> push ecx 10080 <1> ; 10081 000023EA BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table offset 10082 000023EF 89D9 <1> mov ecx, ebx 10083 <1> ; NOTE: 32 (first_page) is initial 10084 <1> ; value of [next_page]. 10085 <1> ; It points to the first available 10086 <1> ; page block for users (ring 3) ... 10087 <1> ; (MAT offset 32 = 1024/32) 10088 <1> ; (at the of the first 4 MB) 10089 000023F1 031D[74670000] <1> add ebx, [next_page] ; Free page searching starts from here 10090 <1> ; next_free_page >> 5 10091 000023F7 030D[78670000] <1> add ecx, [last_page] ; Free page searching ends here 10092 <1> ; (total_pages - 1) >> 5 10093 <1> al_p_scan: 10094 000023FD 39CB <1> cmp ebx, ecx 10095 000023FF 770A <1> ja short al_p_notfound 10096 <1> ; 10097 <1> ; 01/07/2015 10098 <1> ; AMD64 Architecture Programmer’s Manual 10099 <1> ; Volume 3: 10100 <1> ; General-Purpose and System Instructions 10101 <1> ; 10102 <1> ; BSF - Bit Scan Forward 10103 <1> ; 10104 <1> ; Searches the value in a register or a memory location 10105 <1> ; (second operand) for the least-significant set bit. 10106 <1> ; If a set bit is found, the instruction clears the zero flag (ZF) 10107 <1> ; and stores the index of the least-significant set bit in a destination 10108 <1> ; register (first operand). If the second operand contains 0, 10109 <1> ; the instruction sets ZF to 1 and does not change the contents of the 10110 <1> ; destination register. The bit index is an unsigned offset from bit 0 10111 <1> ; of the searched value 10112 <1> ; 10113 00002401 0FBC03 <1> bsf eax, [ebx] ; Scans source operand for first bit set (1). 10114 <1> ; Clear ZF if a bit is found set (1) and 10115 <1> ; loads the destination with an index to 10116 <1> ; first set bit. (0 -> 31) 10117 <1> ; Sets ZF to 1 if no bits are found set. 10118 00002404 751C <1> jnz short al_p_found ; ZF = 0 -> a free page has been found 10119 <1> ; 10120 <1> ; NOTE: a Memory Allocation Table bit 10121 <1> ; with value of 1 means 10122 <1> ; the corresponding page is free 10123 <1> ; (Retro UNIX 386 v1 feature only!) 10124 00002406 83C304 <1> add ebx, 4 10125 <1> ; We return back for searching next page block 10126 <1> ; NOTE: [free_pages] is not ZERO; so, 10127 <1> ; we always will find at least 1 free page here. 10128 00002409 EBF2 <1> jmp short al_p_scan 10129 <1> ; 10130 <1> al_p_notfound: 10131 0000240B 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 10132 00002411 890D[74670000] <1> mov [next_page], ecx ; next/first free page = last page 10133 <1> ; (deallocate_page procedure will change it) 10134 00002417 31C0 <1> xor eax, eax 10135 00002419 A3[70670000] <1> mov [free_pages], eax ; 0 10136 0000241E 59 <1> pop ecx 10137 0000241F 5B <1> pop ebx 10138 <1> ; 10139 <1> ; 17/04/2021 10140 <1> ; ('swap_out' procedure call is disabled as temporary) 10141 <1> 10142 <1> out_of_memory: 10143 <1> ; call swap_out 10144 <1> ; jnc short al_p_ok ; [free_pages] = 0, re-allocation by swap_out 10145 <1> ; ; 10146 <1> ; sub eax, eax ; 0 10147 00002420 F9 <1> stc 10148 00002421 C3 <1> retn 10149 <1> 10150 <1> al_p_found: 10151 00002422 89D9 <1> mov ecx, ebx 10152 00002424 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 10153 0000242A 890D[74670000] <1> mov [next_page], ecx ; Set first free page searching start 10154 <1> ; address/offset (to the next) 10155 00002430 FF0D[70670000] <1> dec dword [free_pages] ; 1 page has been allocated (X = X-1) 10156 <1> ; 10157 00002436 0FB303 <1> btr [ebx], eax ; The destination bit indexed by the source value 10158 <1> ; is copied into the Carry Flag and then cleared 10159 <1> ; in the destination. 10160 <1> ; 10161 <1> ; Reset the bit which is corresponding to the 10162 <1> ; (just) allocated page. 10163 <1> ; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages) 10164 00002439 C1E103 <1> shl ecx, 3 ; (page block offset * 32) + page index 10165 0000243C 01C8 <1> add eax, ecx ; = page number 10166 0000243E C1E00C <1> shl eax, 12 ; physical address of the page (flat/real value) 10167 <1> ; EAX = physical address of memory page 10168 <1> ; 10169 <1> ; NOTE: The relevant page directory and page table entry will be updated 10170 <1> ; according to this EAX value... 10171 00002441 59 <1> pop ecx 10172 00002442 5B <1> pop ebx 10173 <1> al_p_ok: 10174 00002443 C3 <1> retn 10175 <1> 10176 <1> make_page_dir: 10177 <1> ; 18/04/2015 10178 <1> ; 12/04/2015 10179 <1> ; 23/10/2014 10180 <1> ; 16/10/2014 10181 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 10182 <1> ; 10183 <1> ; INPUT -> 10184 <1> ; none 10185 <1> ; OUTPUT -> 10186 <1> ; (EAX = 0) 10187 <1> ; cf = 1 -> insufficient (out of) memory error 10188 <1> ; cf = 0 -> 10189 <1> ; u.pgdir = page directory (physical) address of the current 10190 <1> ; process/user. 10191 <1> ; 10192 <1> ; Modified Registers -> EAX 10193 <1> ; 10194 00002444 E896FFFFFF <1> call allocate_page 10195 00002449 7216 <1> jc short mkpd_error 10196 <1> ; 10197 0000244B A3[046D0000] <1> mov [u.pgdir], eax ; Page dir address for current user/process 10198 <1> ; (Physical address) 10199 <1> clear_page: 10200 <1> ; 18/04/2015 10201 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 10202 <1> ; 10203 <1> ; INPUT -> 10204 <1> ; EAX = physical address of the page 10205 <1> ; OUTPUT -> 10206 <1> ; all bytes of the page will be cleared 10207 <1> ; 10208 <1> ; Modified Registers -> none 10209 <1> ; 10210 00002450 57 <1> push edi 10211 00002451 51 <1> push ecx 10212 00002452 50 <1> push eax 10213 00002453 B900040000 <1> mov ecx, PAGE_SIZE / 4 10214 00002458 89C7 <1> mov edi, eax 10215 0000245A 31C0 <1> xor eax, eax 10216 0000245C F3AB <1> rep stosd 10217 0000245E 58 <1> pop eax 10218 0000245F 59 <1> pop ecx 10219 00002460 5F <1> pop edi 10220 <1> mkpd_error: 10221 <1> mkpt_error: 10222 00002461 C3 <1> retn 10223 <1> 10224 <1> make_page_table: 10225 <1> ; 23/06/2015 10226 <1> ; 18/04/2015 10227 <1> ; 12/04/2015 10228 <1> ; 16/10/2014 10229 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 10230 <1> ; 10231 <1> ; INPUT -> 10232 <1> ; EBX = virtual (linear) address 10233 <1> ; ECX = page table attributes (lower 12 bits) 10234 <1> ; (higher 20 bits must be ZERO) 10235 <1> ; (bit 0 must be 1) 10236 <1> ; u.pgdir = page directory (physical) address 10237 <1> ; OUTPUT -> 10238 <1> ; EDX = Page directory entry address 10239 <1> ; EAX = Page table address 10240 <1> ; cf = 1 -> insufficient (out of) memory error 10241 <1> ; cf = 0 -> page table address in the PDE (EDX) 10242 <1> ; 10243 <1> ; Modified Registers -> EAX, EDX 10244 <1> ; 10245 00002462 E878FFFFFF <1> call allocate_page 10246 00002467 72F8 <1> jc short mkpt_error 10247 00002469 E811000000 <1> call set_pde 10248 0000246E EBE0 <1> jmp short clear_page 10249 <1> 10250 <1> make_page: 10251 <1> ; 24/07/2015 10252 <1> ; 23/06/2015 ; (Retro UNIX 386 v1 - beginning) 10253 <1> ; 10254 <1> ; INPUT -> 10255 <1> ; EBX = virtual (linear) address 10256 <1> ; ECX = page attributes (lower 12 bits) 10257 <1> ; (higher 20 bits must be ZERO) 10258 <1> ; (bit 0 must be 1) 10259 <1> ; u.pgdir = page directory (physical) address 10260 <1> ; OUTPUT -> 10261 <1> ; EBX = Virtual address 10262 <1> ; (EDX = PTE value) 10263 <1> ; EAX = Physical address 10264 <1> ; cf = 1 -> insufficient (out of) memory error 10265 <1> ; 10266 <1> ; Modified Registers -> EAX, EDX 10267 <1> ; 10268 00002470 E86AFFFFFF <1> call allocate_page 10269 00002475 7207 <1> jc short mkp_err 10270 00002477 E821000000 <1> call set_pte 10271 0000247C 73D2 <1> jnc short clear_page ; 18/04/2015 10272 <1> mkp_err: 10273 0000247E C3 <1> retn 10274 <1> 10275 <1> set_pde: ; Set page directory entry (PDE) 10276 <1> ; 20/07/2015 10277 <1> ; 18/04/2015 10278 <1> ; 12/04/2015 10279 <1> ; 23/10/2014 10280 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10281 <1> ; 10282 <1> ; INPUT -> 10283 <1> ; EAX = physical address 10284 <1> ; (use present value if EAX = 0) 10285 <1> ; EBX = virtual (linear) address 10286 <1> ; ECX = page table attributes (lower 12 bits) 10287 <1> ; (higher 20 bits must be ZERO) 10288 <1> ; (bit 0 must be 1) 10289 <1> ; u.pgdir = page directory (physical) address 10290 <1> ; OUTPUT -> 10291 <1> ; EDX = PDE address 10292 <1> ; EAX = page table address (physical) 10293 <1> ; ;(CF=1 -> Invalid page address) 10294 <1> ; 10295 <1> ; Modified Registers -> EDX 10296 <1> ; 10297 0000247F 89DA <1> mov edx, ebx 10298 00002481 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 10299 00002484 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 10300 00002487 0315[046D0000] <1> add edx, [u.pgdir] 10301 <1> ; 10302 0000248D 21C0 <1> and eax, eax 10303 0000248F 7506 <1> jnz short spde_1 10304 <1> ; 10305 00002491 8B02 <1> mov eax, [edx] ; old PDE value 10306 <1> ;test al, 1 10307 <1> ;jz short spde_2 10308 00002493 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 10309 <1> spde_1: 10310 <1> ;and cx, 0FFFh 10311 00002497 8902 <1> mov [edx], eax 10312 00002499 66090A <1> or [edx], cx 10313 0000249C C3 <1> retn 10314 <1> ;spde_2: ; error 10315 <1> ; stc 10316 <1> ; retn 10317 <1> 10318 <1> set_pte: ; Set page table entry (PTE) 10319 <1> ; 24/07/2015 10320 <1> ; 20/07/2015 10321 <1> ; 23/06/2015 10322 <1> ; 18/04/2015 10323 <1> ; 12/04/2015 10324 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10325 <1> ; 10326 <1> ; INPUT -> 10327 <1> ; EAX = physical page address 10328 <1> ; (use present value if EAX = 0) 10329 <1> ; EBX = virtual (linear) address 10330 <1> ; ECX = page attributes (lower 12 bits) 10331 <1> ; (higher 20 bits must be ZERO) 10332 <1> ; (bit 0 must be 1) 10333 <1> ; u.pgdir = page directory (physical) address 10334 <1> ; OUTPUT -> 10335 <1> ; EAX = physical page address 10336 <1> ; (EDX = PTE value) 10337 <1> ; EBX = virtual address 10338 <1> ; 10339 <1> ; CF = 1 -> error 10340 <1> ; 10341 <1> ; Modified Registers -> EAX, EDX 10342 <1> ; 10343 0000249D 50 <1> push eax 10344 0000249E A1[046D0000] <1> mov eax, [u.pgdir] ; 20/07/2015 10345 000024A3 E837000000 <1> call get_pde 10346 <1> ; EDX = PDE address 10347 <1> ; EAX = PDE value 10348 000024A8 5A <1> pop edx ; physical page address 10349 000024A9 722A <1> jc short spte_err ; PDE not present 10350 <1> ; 10351 000024AB 53 <1> push ebx ; 24/07/2015 10352 000024AC 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 10353 <1> ; EDX = PT address (physical) 10354 000024B0 C1EB0C <1> shr ebx, PAGE_SHIFT ; 12 10355 000024B3 81E3FF030000 <1> and ebx, PTE_MASK ; 03FFh 10356 <1> ; clear higher 10 bits (PD bits) 10357 000024B9 C1E302 <1> shl ebx, 2 ; offset to page table (1024*4) 10358 000024BC 01C3 <1> add ebx, eax 10359 <1> ; 10360 000024BE 8B03 <1> mov eax, [ebx] ; Old PTE value 10361 000024C0 A801 <1> test al, 1 10362 000024C2 740C <1> jz short spte_0 10363 000024C4 09D2 <1> or edx, edx 10364 000024C6 750F <1> jnz short spte_1 10365 000024C8 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits 10366 000024CC 89C2 <1> mov edx, eax 10367 000024CE EB09 <1> jmp short spte_2 10368 <1> spte_0: 10369 <1> ; If this PTE contains a swap (disk) address, 10370 <1> ; it can be updated by using 'swap_in' procedure 10371 <1> ; only! 10372 000024D0 21C0 <1> and eax, eax 10373 000024D2 7403 <1> jz short spte_1 10374 <1> ; 24/07/2015 10375 <1> ; swapped page ! (on disk) 10376 000024D4 5B <1> pop ebx 10377 <1> spte_err: 10378 000024D5 F9 <1> stc 10379 000024D6 C3 <1> retn 10380 <1> spte_1: 10381 000024D7 89D0 <1> mov eax, edx 10382 <1> spte_2: 10383 000024D9 09CA <1> or edx, ecx 10384 <1> ; 23/06/2015 10385 000024DB 8913 <1> mov [ebx], edx ; PTE value in EDX 10386 <1> ; 24/07/2015 10387 000024DD 5B <1> pop ebx 10388 000024DE C3 <1> retn 10389 <1> 10390 <1> get_pde: ; Get present value of the relevant PDE 10391 <1> ; 20/07/2015 10392 <1> ; 18/04/2015 10393 <1> ; 12/04/2015 10394 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10395 <1> ; 10396 <1> ; INPUT -> 10397 <1> ; EBX = virtual (linear) address 10398 <1> ; EAX = page directory (physical) address 10399 <1> ; OUTPUT -> 10400 <1> ; EDX = Page directory entry address 10401 <1> ; EAX = Page directory entry value 10402 <1> ; CF = 1 -> PDE not present or invalid ? 10403 <1> ; Modified Registers -> EDX, EAX 10404 <1> ; 10405 000024DF 89DA <1> mov edx, ebx 10406 000024E1 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 (12+10) 10407 000024E4 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 10408 000024E7 01C2 <1> add edx, eax ; page directory address (physical) 10409 000024E9 8B02 <1> mov eax, [edx] 10410 000024EB A801 <1> test al, PDE_A_PRESENT ; page table is present or not ! 10411 000024ED 751F <1> jnz short gpte_retn 10412 000024EF F9 <1> stc 10413 <1> gpde_retn: 10414 000024F0 C3 <1> retn 10415 <1> 10416 <1> get_pte: 10417 <1> ; Get present value of the relevant PTE 10418 <1> ; 29/07/2015 10419 <1> ; 20/07/2015 10420 <1> ; 18/04/2015 10421 <1> ; 12/04/2015 10422 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10423 <1> ; 10424 <1> ; INPUT -> 10425 <1> ; EBX = virtual (linear) address 10426 <1> ; EAX = page directory (physical) address 10427 <1> ; OUTPUT -> 10428 <1> ; EDX = Page table entry address (if CF=0) 10429 <1> ; Page directory entry address (if CF=1) 10430 <1> ; (Bit 0 value is 0 if PT is not present) 10431 <1> ; EAX = Page table entry value (page address) 10432 <1> ; CF = 1 -> PDE not present or invalid ? 10433 <1> ; Modified Registers -> EAX, EDX 10434 <1> ; 10435 000024F1 E8E9FFFFFF <1> call get_pde 10436 000024F6 72F8 <1> jc short gpde_retn ; page table is not present 10437 <1> ;jnc short gpte_1 10438 <1> ;retn 10439 <1> ;gpte_1: 10440 000024F8 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 10441 000024FC 89DA <1> mov edx, ebx 10442 000024FE C1EA0C <1> shr edx, PAGE_SHIFT ; 12 10443 00002501 81E2FF030000 <1> and edx, PTE_MASK ; 03FFh 10444 <1> ; clear higher 10 bits (PD bits) 10445 00002507 C1E202 <1> shl edx, 2 ; offset from start of page table (1024*4) 10446 0000250A 01C2 <1> add edx, eax 10447 0000250C 8B02 <1> mov eax, [edx] 10448 <1> gpte_retn: 10449 0000250E C3 <1> retn 10450 <1> 10451 <1> deallocate_page_dir: 10452 <1> ; 15/09/2015 10453 <1> ; 05/08/2015 10454 <1> ; 30/04/2015 10455 <1> ; 28/04/2015 10456 <1> ; 17/10/2014 10457 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 10458 <1> ; 10459 <1> ; INPUT -> 10460 <1> ; EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD) 10461 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 10462 <1> ; OUTPUT -> 10463 <1> ; All of page tables in the page directory 10464 <1> ; and page dir's itself will be deallocated 10465 <1> ; except 'read only' duplicated pages (will be converted 10466 <1> ; to writable pages). 10467 <1> ; 10468 <1> ; Modified Registers -> EAX 10469 <1> ; 10470 <1> ; 10471 0000250F 56 <1> push esi 10472 00002510 51 <1> push ecx 10473 00002511 50 <1> push eax 10474 00002512 89C6 <1> mov esi, eax 10475 00002514 31C9 <1> xor ecx, ecx 10476 <1> ; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB), 10477 <1> ; it must not be deallocated 10478 00002516 890E <1> mov [esi], ecx ; 0 ; clear PDE 0 10479 <1> dapd_0: 10480 00002518 AD <1> lodsd 10481 00002519 A801 <1> test al, PDE_A_PRESENT ; bit 0, present flag (must be 1) 10482 0000251B 7409 <1> jz short dapd_1 10483 0000251D 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 10484 00002521 E812000000 <1> call deallocate_page_table 10485 <1> dapd_1: 10486 00002526 41 <1> inc ecx ; page directory entry index 10487 00002527 81F900040000 <1> cmp ecx, PAGE_SIZE / 4 ; 1024 10488 0000252D 72E9 <1> jb short dapd_0 10489 <1> dapd_2: 10490 0000252F 58 <1> pop eax 10491 00002530 E870000000 <1> call deallocate_page ; deallocate the page dir's itself 10492 00002535 59 <1> pop ecx 10493 00002536 5E <1> pop esi 10494 00002537 C3 <1> retn 10495 <1> 10496 <1> deallocate_page_table: 10497 <1> ; 17/07/2022 10498 <1> ; 17/04/2021 - Retro UNIX 386 v2 10499 <1> ; (temporary modifications) 10500 <1> ; 12/07/2016 (TRDOS 386 v2) 10501 <1> ; 19/09/2015 10502 <1> ; 15/09/2015 10503 <1> ; 05/08/2015 10504 <1> ; 30/04/2015 10505 <1> ; 28/04/2015 10506 <1> ; 24/10/2014 10507 <1> ; 23/10/2014 10508 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 10509 <1> ; 10510 <1> ; INPUT -> 10511 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE 10512 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 10513 <1> ; (ECX = page directory entry index) 10514 <1> ; OUTPUT -> 10515 <1> ; All of pages in the page table and page table's itself 10516 <1> ; will be deallocated except 'read only' duplicated pages 10517 <1> ; (will be converted to writable pages). 10518 <1> ; 10519 <1> ; Modified Registers -> EAX 10520 <1> ; 10521 00002538 56 <1> push esi 10522 00002539 57 <1> push edi 10523 0000253A 52 <1> push edx 10524 0000253B 50 <1> push eax ; * 10525 0000253C 89C6 <1> mov esi, eax 10526 0000253E 31FF <1> xor edi, edi ; 0 10527 <1> dapt_0: 10528 00002540 AD <1> lodsd 10529 00002541 A801 <1> test al, PTE_A_PRESENT ; bit 0, present flag (must be 1) 10530 00002543 7453 <1> jz short dapt_1 10531 <1> ; 10532 00002545 A802 <1> test al, PTE_A_WRITE ; bit 1, writable (r/w) flag 10533 <1> ; (must be 1) 10534 00002547 753D <1> jnz short dapt_3 10535 <1> ; Read only -duplicated- page (belongs to a parent or a child) 10536 00002549 66A90002 <1> test ax, PTE_DUPLICATED ; Was this page duplicated 10537 <1> ; as child's page ? 10538 0000254D 7442 <1> jz short dapt_4 ; Clear PTE but don't deallocate the page! 10539 <1> ; check the parent's PTE value is read only & same page or not.. 10540 <1> ; ECX = page directory entry index (0-1023) 10541 0000254F 53 <1> push ebx 10542 00002550 51 <1> push ecx 10543 <1> ;shl cx, 2 ; *4 10544 <1> ; 17/07/2022 10545 00002551 C1E102 <1> shl ecx, 2 10546 00002554 01CB <1> add ebx, ecx ; PDE offset (for the parent) 10547 00002556 8B0B <1> mov ecx, [ebx] 10548 00002558 F6C101 <1> test cl, PDE_A_PRESENT ; present (valid) or not ? 10549 0000255B 7427 <1> jz short dapt_2 ; parent process does not use this page 10550 0000255D 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 10551 <1> ; EDI = page table entry index (0-1023) 10552 00002562 89FA <1> mov edx, edi 10553 <1> ;shl dx, 2 ; *4 10554 <1> ; 17/07/2022 10555 00002564 C1E202 <1> shl edx, 2 10556 00002567 01CA <1> add edx, ecx ; PTE offset (for the parent) 10557 00002569 8B1A <1> mov ebx, [edx] 10558 0000256B F6C301 <1> test bl, PTE_A_PRESENT ; present or not ? 10559 0000256E 7414 <1> jz short dapt_2 ; parent process does not use this page 10560 00002570 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 10561 00002574 6681E300F0 <1> and bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 10562 00002579 39D8 <1> cmp eax, ebx ; parent's and child's pages are same ? 10563 0000257B 7507 <1> jne short dapt_2 ; not same page 10564 <1> ; deallocate the child's page 10565 0000257D 800A02 <1> or byte [edx], PTE_A_WRITE ; convert to writable page (parent) 10566 00002580 59 <1> pop ecx 10567 00002581 5B <1> pop ebx 10568 00002582 EB0D <1> jmp short dapt_4 10569 <1> 10570 <1> ; 17/04/2021 10571 <1> ; ('dapt_1' is disabled as temporary) 10572 <1> ; 10573 <1> ;dapt_1: 10574 <1> ; or eax, eax ; swapped page ? 10575 <1> ; jz short dapt_5 ; no 10576 <1> ; ; yes 10577 <1> ; shr eax, 1 10578 <1> ; call unlink_swap_block ; Deallocate swapped page block 10579 <1> ; ; on the swap disk (or in file) 10580 <1> ; jmp short dapt_5 10581 <1> dapt_2: 10582 00002584 59 <1> pop ecx 10583 00002585 5B <1> pop ebx 10584 <1> dapt_3: 10585 <1> ; 12/07/2016 10586 00002586 66A90004 <1> test ax, PTE_SHARED ; shared or direct memory access indicator 10587 0000258A 7505 <1> jnz short dapt_4 ; AVL bit 1 = 1, do not deallocate this page! 10588 <1> ; 10589 <1> ;and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 10590 0000258C E814000000 <1> call deallocate_page ; set the mem allocation bit of this page 10591 <1> dapt_4: 10592 00002591 C746FC00000000 <1> mov dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent) 10593 <1> dapt_1: ; 17/04/2021 (temporary) 10594 <1> dapt_5: 10595 00002598 47 <1> inc edi ; page table entry index 10596 00002599 81FF00040000 <1> cmp edi, PAGE_SIZE / 4 ; 1024 10597 0000259F 729F <1> jb short dapt_0 10598 <1> ; 10599 000025A1 58 <1> pop eax ; * 10600 000025A2 5A <1> pop edx 10601 000025A3 5F <1> pop edi 10602 000025A4 5E <1> pop esi 10603 <1> ; 10604 <1> ;call deallocate_page ; deallocate the page table's itself 10605 <1> ;retn 10606 <1> 10607 <1> deallocate_page: 10608 <1> ; 15/09/2015 10609 <1> ; 28/04/2015 10610 <1> ; 10/03/2015 10611 <1> ; 17/10/2014 10612 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 10613 <1> ; 10614 <1> ; INPUT -> 10615 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 10616 <1> ; OUTPUT -> 10617 <1> ; [free_pages] is increased 10618 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is SET) 10619 <1> ; CF = 1 if the page is already deallocated 10620 <1> ; (or not allocated) before. 10621 <1> ; 10622 <1> ; Modified Registers -> EAX 10623 <1> ; 10624 000025A5 53 <1> push ebx 10625 000025A6 52 <1> push edx 10626 <1> ; 10627 000025A7 C1E80C <1> shr eax, PAGE_SHIFT ; shift physical address to 10628 <1> ; 12 bits right 10629 <1> ; to get page number 10630 000025AA 89C2 <1> mov edx, eax 10631 <1> ; 15/09/2015 10632 000025AC C1EA03 <1> shr edx, 3 ; to get offset to M.A.T. 10633 <1> ; (1 allocation bit = 1 page) 10634 <1> ; (1 allocation bytes = 8 pages) 10635 000025AF 80E2FC <1> and dl, 0FCh ; clear lower 2 bits 10636 <1> ; (to get 32 bit position) 10637 <1> ; 10638 000025B2 BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table address 10639 000025B7 01D3 <1> add ebx, edx 10640 000025B9 83E01F <1> and eax, 1Fh ; lower 5 bits only 10641 <1> ; (allocation bit position) 10642 000025BC 3B15[74670000] <1> cmp edx, [next_page] ; is the new free page address lower 10643 <1> ; than the address in 'next_page' ? 10644 <1> ; (next/first free page value) 10645 000025C2 7306 <1> jnb short dap_1 ; no 10646 000025C4 8915[74670000] <1> mov [next_page], edx ; yes 10647 <1> dap_1: 10648 000025CA 0FAB03 <1> bts [ebx], eax ; unlink/release/deallocate page 10649 <1> ; set relevant bit to 1. 10650 <1> ; set CF to the previous bit value 10651 <1> ;cmc ; complement carry flag 10652 <1> ;jc short dap_2 ; do not increase free_pages count 10653 <1> ; if the page is already deallocated 10654 <1> ; before. 10655 000025CD FF05[70670000] <1> inc dword [free_pages] 10656 <1> dap_2: 10657 000025D3 5A <1> pop edx 10658 000025D4 5B <1> pop ebx 10659 000025D5 C3 <1> retn 10660 <1> 10661 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10662 <1> ;; ;; 10663 <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; 10664 <1> ;; Distributed under terms of the GNU General Public License ;; 10665 <1> ;; ;; 10666 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10667 <1> 10668 <1> ;;$Revision: 5057 $ 10669 <1> 10670 <1> 10671 <1> ;;align 4 10672 <1> ;;proc alloc_page 10673 <1> 10674 <1> ;; pushfd 10675 <1> ;; cli 10676 <1> ;; push ebx 10677 <1> ;;;//- 10678 <1> ;; cmp [pg_data.pages_free], 1 10679 <1> ;; jle .out_of_memory 10680 <1> ;;;//- 10681 <1> ;; 10682 <1> ;; mov ebx, [page_start] 10683 <1> ;; mov ecx, [page_end] 10684 <1> ;;.l1: 10685 <1> ;; bsf eax, [ebx]; 10686 <1> ;; jnz .found 10687 <1> ;; add ebx, 4 10688 <1> ;; cmp ebx, ecx 10689 <1> ;; jb .l1 10690 <1> ;; pop ebx 10691 <1> ;; popfd 10692 <1> ;; xor eax, eax 10693 <1> ;; ret 10694 <1> ;;.found: 10695 <1> ;;;//- 10696 <1> ;; dec [pg_data.pages_free] 10697 <1> ;; jz .out_of_memory 10698 <1> ;;;//- 10699 <1> ;; btr [ebx], eax 10700 <1> ;; mov [page_start], ebx 10701 <1> ;; sub ebx, sys_pgmap 10702 <1> ;; lea eax, [eax+ebx*8] 10703 <1> ;; shl eax, 12 10704 <1> ;;;//- dec [pg_data.pages_free] 10705 <1> ;; pop ebx 10706 <1> ;; popfd 10707 <1> ;; ret 10708 <1> ;;;//- 10709 <1> ;;.out_of_memory: 10710 <1> ;; mov [pg_data.pages_free], 1 10711 <1> ;; xor eax, eax 10712 <1> ;; pop ebx 10713 <1> ;; popfd 10714 <1> ;; ret 10715 <1> ;;;//- 10716 <1> ;;endp 10717 <1> 10718 <1> duplicate_page_dir: 10719 <1> ; 21/09/2015 10720 <1> ; 31/08/2015 10721 <1> ; 20/07/2015 10722 <1> ; 28/04/2015 10723 <1> ; 27/04/2015 10724 <1> ; 18/04/2015 10725 <1> ; 12/04/2015 10726 <1> ; 18/10/2014 10727 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 10728 <1> ; 10729 <1> ; INPUT -> 10730 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 10731 <1> ; page directory. 10732 <1> ; OUTPUT -> 10733 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 10734 <1> ; page directory. 10735 <1> ; (New page directory with new page table entries.) 10736 <1> ; (New page tables with read only copies of the parent's 10737 <1> ; pages.) 10738 <1> ; EAX = 0 -> Error (CF = 1) 10739 <1> ; 10740 <1> ; Modified Registers -> none (except EAX) 10741 <1> ; 10742 000025D6 E804FEFFFF <1> call allocate_page 10743 000025DB 723E <1> jc short dpd_err 10744 <1> ; 10745 000025DD 55 <1> push ebp ; 20/07/2015 10746 000025DE 56 <1> push esi 10747 000025DF 57 <1> push edi 10748 000025E0 53 <1> push ebx 10749 000025E1 51 <1> push ecx 10750 000025E2 8B35[046D0000] <1> mov esi, [u.pgdir] 10751 000025E8 89C7 <1> mov edi, eax 10752 000025EA 50 <1> push eax ; save child's page directory address 10753 <1> ; 31/08/2015 10754 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 10755 <1> ; (use same system space for all user page tables) 10756 000025EB A5 <1> movsd 10757 000025EC BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 10758 000025F1 B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 10759 <1> dpd_0: 10760 000025F6 AD <1> lodsd 10761 <1> ;or eax, eax 10762 <1> ;jnz short dpd_1 10763 000025F7 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 10764 000025F9 7508 <1> jnz short dpd_1 10765 <1> ; 20/07/2015 (virtual address at the end of the page table) 10766 000025FB 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 10767 00002601 EB0F <1> jmp short dpd_2 10768 <1> dpd_1: 10769 00002603 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 10770 00002607 89C3 <1> mov ebx, eax 10771 <1> ; EBX = Parent's page table address 10772 00002609 E81F000000 <1> call duplicate_page_table 10773 0000260E 720C <1> jc short dpd_p_err 10774 <1> ; EAX = Child's page table address 10775 00002610 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 10776 <1> ; set bit 0, bit 1 and bit 2 to 1 10777 <1> ; (present, writable, user) 10778 <1> dpd_2: 10779 00002612 AB <1> stosd 10780 00002613 E2E1 <1> loop dpd_0 10781 <1> ; 10782 00002615 58 <1> pop eax ; restore child's page directory address 10783 <1> dpd_3: 10784 00002616 59 <1> pop ecx 10785 00002617 5B <1> pop ebx 10786 00002618 5F <1> pop edi 10787 00002619 5E <1> pop esi 10788 0000261A 5D <1> pop ebp ; 20/07/2015 10789 <1> dpd_err: 10790 0000261B C3 <1> retn 10791 <1> dpd_p_err: 10792 <1> ; release the allocated pages missing (recover free space) 10793 0000261C 58 <1> pop eax ; the new page directory address (physical) 10794 0000261D 8B1D[046D0000] <1> mov ebx, [u.pgdir] ; parent's page directory address 10795 00002623 E8E7FEFFFF <1> call deallocate_page_dir 10796 00002628 29C0 <1> sub eax, eax ; 0 10797 0000262A F9 <1> stc 10798 0000262B EBE9 <1> jmp short dpd_3 10799 <1> 10800 <1> duplicate_page_table: 10801 <1> ; 31/12/2021 - Retro UNIX 386 v1.2 10802 <1> ; 17/04/2021 - Retro UNIX 386 v2 10803 <1> ; (temporary modifications) 10804 <1> ; 16/04/2021 (Retro UNIX 386 v2) 10805 <1> ; 20/02/2017 (TRDOS 386 v2) 10806 <1> ; 21/09/2015 10807 <1> ; 20/07/2015 10808 <1> ; 05/05/2015 10809 <1> ; 28/04/2015 10810 <1> ; 27/04/2015 10811 <1> ; 18/04/2015 10812 <1> ; 18/10/2014 10813 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 10814 <1> ; 10815 <1> ; INPUT -> 10816 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 10817 <1> ; 20/02/2017 10818 <1> ; EBP = Linear address of the page (from 'duplicate_page_dir') 10819 <1> ; (Linear address = CORE + user's virtual address) 10820 <1> ; OUTPUT -> 10821 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 10822 <1> ; (with 'read only' attribute of page table entries) 10823 <1> ; 20/02/2017 10824 <1> ; EBP = Next linear page address (for 'duplicate_page_dir') 10825 <1> ; 10826 <1> ; CF = 1 -> error 10827 <1> ; 10828 <1> ; Modified Registers -> EBP (except EAX) 10829 <1> ; 10830 0000262D E8ADFDFFFF <1> call allocate_page 10831 00002632 725B <1> jc short dpt_err 10832 <1> ; 10833 00002634 50 <1> push eax ; * 10834 00002635 56 <1> push esi 10835 00002636 57 <1> push edi 10836 00002637 52 <1> push edx 10837 00002638 51 <1> push ecx 10838 <1> ; 10839 00002639 89DE <1> mov esi, ebx 10840 0000263B 89C7 <1> mov edi, eax 10841 0000263D 89C2 <1> mov edx, eax 10842 0000263F 81C200100000 <1> add edx, PAGE_SIZE 10843 <1> dpt_0: 10844 00002645 AD <1> lodsd 10845 00002646 21C0 <1> and eax, eax 10846 00002648 7435 <1> jz short dpt_3 10847 0000264A A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 10848 <1> ; 17/04/2021 (temporary) 10849 0000264C 7503 <1> jnz short dpt_1 10850 <1> ;jz short dpt_p_err 10851 <1> ; 31/12/2021 10852 0000264E F9 <1> stc 10853 0000264F EB39 <1> jmp short dpt_p_err 10854 <1> 10855 <1> ; 17/04/2021 10856 <1> ; ('reload_page' procedure call is disabled as temporary) 10857 <1> ; 10858 <1> ; ; 20/07/2015 10859 <1> ; ; ebp = virtual (linear) address of the memory page 10860 <1> ; call reload_page ; 28/04/2015 10861 <1> ; jc short dpt_p_err 10862 <1> dpt_1: 10863 <1> ; 21/09/2015 10864 00002651 89C1 <1> mov ecx, eax 10865 00002653 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 10866 00002657 F6C102 <1> test cl, PTE_A_WRITE ; writable page ? 10867 0000265A 751A <1> jnz short dpt_2 10868 <1> ; Read only (parent) page 10869 <1> ; - there is a third process which uses this page - 10870 <1> ; Allocate a new page for the child process 10871 0000265C E87EFDFFFF <1> call allocate_page 10872 00002661 7227 <1> jc short dpt_p_err 10873 00002663 57 <1> push edi 10874 00002664 56 <1> push esi 10875 00002665 89CE <1> mov esi, ecx 10876 00002667 89C7 <1> mov edi, eax 10877 00002669 B900040000 <1> mov ecx, PAGE_SIZE/4 10878 0000266E F3A5 <1> rep movsd ; copy page (4096 bytes) 10879 00002670 5E <1> pop esi 10880 00002671 5F <1> pop edi 10881 <1> ; 10882 <1> 10883 <1> ; 17/04/2021 10884 <1> ; ('add_to_swap_queue' procedure call is disabled as temporary) 10885 <1> ; 10886 <1> ; push ebx 10887 <1> ; push eax 10888 <1> ; ; 20/07/2015 10889 <1> ; mov ebx, ebp 10890 <1> ; ; ebx = virtual (linear) address of the memory page 10891 <1> ; call add_to_swap_queue 10892 <1> ; pop eax 10893 <1> ; pop ebx 10894 <1> 10895 <1> ; 21/09/2015 10896 00002672 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 10897 <1> ; user + writable + present page 10898 00002674 EB09 <1> jmp short dpt_3 10899 <1> dpt_2: 10900 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 10901 00002676 0C05 <1> or al, PTE_A_USER+PTE_A_PRESENT 10902 <1> ; (read only page!) 10903 00002678 8946FC <1> mov [esi-4], eax ; update parent's PTE 10904 0000267B 660D0002 <1> or ax, PTE_DUPLICATED ; (read only page & duplicated PTE!) 10905 <1> dpt_3: 10906 0000267F AB <1> stosd ; EDI points to child's PTE 10907 <1> ; 10908 00002680 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 10909 <1> ; 10910 00002686 39D7 <1> cmp edi, edx 10911 00002688 72BB <1> jb short dpt_0 10912 <1> dpt_p_err: 10913 0000268A 59 <1> pop ecx 10914 0000268B 5A <1> pop edx 10915 0000268C 5F <1> pop edi 10916 0000268D 5E <1> pop esi 10917 0000268E 58 <1> pop eax ; * 10918 <1> dpt_err: 10919 0000268F C3 <1> retn 10920 <1> 10921 <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault ! 10922 <1> ; 31/12/2021 - Retro UNIX 386 v1.2 10923 <1> ; 17/04/2021 - Retro UNIX 386 v2 10924 <1> ; (temporary modifications) 10925 <1> ; 21/09/2015 10926 <1> ; 19/09/2015 10927 <1> ; 17/09/2015 10928 <1> ; 28/08/2015 10929 <1> ; 20/07/2015 10930 <1> ; 28/06/2015 10931 <1> ; 03/05/2015 10932 <1> ; 30/04/2015 10933 <1> ; 18/04/2015 10934 <1> ; 12/04/2015 10935 <1> ; 30/10/2014 10936 <1> ; 11/09/2014 10937 <1> ; 10/09/2014 (Retro UNIX 386 v1 - beginning) 10938 <1> ; 10939 <1> ; Note: This is not an interrupt/exception handler. 10940 <1> ; This is a 'page fault remedy' subroutine 10941 <1> ; which will be called by standard/uniform 10942 <1> ; exception handler. 10943 <1> ; 10944 <1> ; INPUT -> 10945 <1> ; [error_code] = 32 bit ERROR CODE (lower 5 bits are valid) 10946 <1> ; 10947 <1> ; cr2 = the virtual (linear) address 10948 <1> ; which has caused to page fault (19/09/2015) 10949 <1> ; 10950 <1> ; OUTPUT -> 10951 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 10952 <1> ; EAX = 0 -> no error 10953 <1> ; EAX > 0 -> error code in EAX (also CF = 1) 10954 <1> ; 10955 <1> ; Modified Registers -> none (except EAX) 10956 <1> ; 10957 <1> ; 10958 <1> ; ERROR CODE: 10959 <1> ; 31 ..... 4 3 2 1 0 10960 <1> ; +---+-- --+---+---+---+---+---+---+ 10961 <1> ; | Reserved | I | R | U | W | P | 10962 <1> ; +---+-- --+---+---+---+---+---+---+ 10963 <1> ; 10964 <1> ; P : PRESENT - When set, the page fault was caused by 10965 <1> ; a page-protection violation. When not set, 10966 <1> ; it was caused by a non-present page. 10967 <1> ; W : WRITE - When set, the page fault was caused by 10968 <1> ; a page write. When not set, it was caused 10969 <1> ; by a page read. 10970 <1> ; U : USER - When set, the page fault was caused 10971 <1> ; while CPL = 3. 10972 <1> ; This does not necessarily mean that 10973 <1> ; the page fault was a privilege violation. 10974 <1> ; R : RESERVD - When set, the page fault was caused by 10975 <1> ; WRITE reading a 1 in a reserved field. 10976 <1> ; I : INSTRUC - When set, the page fault was caused by 10977 <1> ; FETCH an instruction fetch 10978 <1> ; 10979 <1> ;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION 10980 <1> ; 31 22 12 11 0 10981 <1> ; +-------------------+-------------------+-----------------------+ 10982 <1> ; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # | OFFSET | 10983 <1> ; +-------------------+-------------------+-----------------------+ 10984 <1> ; 10985 <1> 10986 <1> ;; CR3 REGISTER (Control Register 3) 10987 <1> ; 31 12 5 4 3 2 0 10988 <1> ; +---------------------------------------+-------------+---+-----+ 10989 <1> ; | | |P|P| | 10990 <1> ; | PAGE DIRECTORY TABLE BASE ADDRESS | reserved |C|W|rsvrd| 10991 <1> ; | | |D|T| | 10992 <1> ; +---------------------------------------+-------------+---+-----+ 10993 <1> ; 10994 <1> ; PWT - WRITE THROUGH 10995 <1> ; PCD - CACHE DISABLE 10996 <1> ; 10997 <1> ; 10998 <1> ;; x86 PAGE DIRECTORY ENTRY (4 KByte Page) 10999 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 11000 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11001 <1> ; | | | | | | |P|P|U|R| | 11002 <1> ; | PAGE TABLE BASE ADDRESS 31..12 | AVL |G|0|D|A|C|W|/|/|P| 11003 <1> ; | | | | | | |D|T|S|W| | 11004 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11005 <1> ; 11006 <1> ; P - PRESENT 11007 <1> ; R/W - READ/WRITE 11008 <1> ; U/S - USER/SUPERVISOR 11009 <1> ; PWT - WRITE THROUGH 11010 <1> ; PCD - CACHE DISABLE 11011 <1> ; A - ACCESSED 11012 <1> ; D - DIRTY (IGNORED) 11013 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 11014 <1> ; G - GLOBAL (IGNORED) 11015 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 11016 <1> ; 11017 <1> ; 11018 <1> ;; x86 PAGE TABLE ENTRY (4 KByte Page) 11019 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 11020 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11021 <1> ; | | | |P| | |P|P|U|R| | 11022 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |G|A|D|A|C|W|/|/|P| 11023 <1> ; | | | |T| | |D|T|S|W| | 11024 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11025 <1> ; 11026 <1> ; P - PRESENT 11027 <1> ; R/W - READ/WRITE 11028 <1> ; U/S - USER/SUPERVISOR 11029 <1> ; PWT - WRITE THROUGH 11030 <1> ; PCD - CACHE DISABLE 11031 <1> ; A - ACCESSED 11032 <1> ; D - DIRTY 11033 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 11034 <1> ; G - GLOBAL 11035 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 11036 <1> ; 11037 <1> ; 11038 <1> ;; 80386 PAGE TABLE ENTRY (4 KByte Page) 11039 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 11040 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 11041 <1> ; | | | | | | | | |U|R| | 11042 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |0|0|D|A|0|0|/|/|P| 11043 <1> ; | | | | | | | | |S|W| | 11044 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 11045 <1> ; 11046 <1> ; P - PRESENT 11047 <1> ; R/W - READ/WRITE 11048 <1> ; U/S - USER/SUPERVISOR 11049 <1> ; D - DIRTY 11050 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 11051 <1> ; 11052 <1> ; NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE. 11053 <1> ; 11054 <1> ; 11055 <1> ;; Invalid Page Table Entry 11056 <1> ; 31 1 0 11057 <1> ; +-------------------------------------------------------------+-+ 11058 <1> ; | | | 11059 <1> ; | AVAILABLE |0| 11060 <1> ; | | | 11061 <1> ; +-------------------------------------------------------------+-+ 11062 <1> ; 11063 <1> 11064 00002690 53 <1> push ebx 11065 00002691 52 <1> push edx 11066 00002692 51 <1> push ecx 11067 <1> ; 11068 <1> ; 21/09/2015 (debugging) 11069 00002693 FF05[1C6D0000] <1> inc dword [u.pfcount] ; page fault count for running process 11070 00002699 FF05[1C680000] <1> inc dword [PF_Count] ; total page fault count 11071 <1> ; 28/06/2015 11072 <1> ;mov edx, [error_code] ; Lower 5 bits are valid 11073 0000269F 8A15[14680000] <1> mov dl, [error_code] 11074 <1> ; 11075 000026A5 F6C201 <1> test dl, 1 ; page fault was caused by a non-present page 11076 <1> ; sign 11077 000026A8 7416 <1> jz short pfh_alloc_np 11078 <1> ; 11079 <1> ; If it is not a 'write on read only page' type page fault 11080 <1> ; major page fault error with minor reason must be returned without 11081 <1> ; fixing the problem. 'sys_exit with error' will be needed 11082 <1> ; after return here! 11083 <1> ; Page fault will be remedied, by copying page contents 11084 <1> ; to newly allocated page with write permission; 11085 <1> ; sys_fork -> sys_exec -> copy on write, demand paging method is 11086 <1> ; used for working with minimum possible memory usage. 11087 <1> ; sys_fork will duplicate page directory and tables of parent 11088 <1> ; process with 'read only' flag. If the child process attempts to 11089 <1> ; write on these read only pages, page fault will be directed here 11090 <1> ; for allocating a new page with same data/content. 11091 <1> ; 11092 <1> ; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS) 11093 <1> ; will not force to separate CODE and DATA space 11094 <1> ; in a process/program... 11095 <1> ; CODE segment/section may contain DATA! 11096 <1> ; It is flat, smoth and simplest programming method already as in 11097 <1> ; Retro UNIX 8086 v1 and MS-DOS programs. 11098 <1> ; 11099 000026AA F6C202 <1> test dl, 2 ; page fault was caused by a page write 11100 <1> ; sign 11101 000026AD 744F <1> jz short pfh_p_err 11102 <1> ; 31/08/2015 11103 000026AF F6C204 <1> test dl, 4 ; page fault was caused while CPL = 3 (user mode) 11104 <1> ; sign. (U+W+P = 4+2+1 = 7) 11105 000026B2 744A <1> jz short pfh_pv_err 11106 <1> ; 11107 <1> ; make a new page and copy the parent's page content 11108 <1> ; as the child's new page content 11109 <1> ; 11110 000026B4 0F20D3 <1> mov ebx, cr2 ; CR2 contains the linear address 11111 <1> ; which has caused to page fault 11112 000026B7 E87C000000 <1> call copy_page 11113 000026BC 7239 <1> jc short pfh_im_err ; insufficient memory 11114 <1> ; 11115 000026BE EB72 <1> jmp pfh_cpp_ok 11116 <1> ; 11117 <1> pfh_alloc_np: 11118 000026C0 E81AFDFFFF <1> call allocate_page ; (allocate a new page) 11119 000026C5 7230 <1> jc short pfh_im_err ; 'insufficient memory' error 11120 <1> pfh_chk_cpl: 11121 <1> ; EAX = Physical (base) address of the allocated (new) page 11122 <1> ; (Lower 12 bits are ZERO, because 11123 <1> ; the address is on a page boundary) 11124 000026C7 80E204 <1> and dl, 4 ; CPL = 3 ? 11125 000026CA 7505 <1> jnz short pfh_um 11126 <1> ; Page fault handler for kernel/system mode (CPL=0) 11127 000026CC 0F20DB <1> mov ebx, cr3 ; CR3 (Control Register 3) contains physical address 11128 <1> ; of the current/active page directory 11129 <1> ; (Always kernel/system mode page directory, here!) 11130 <1> ; Note: Lower 12 bits are 0. (page boundary) 11131 000026CF EB06 <1> jmp short pfh_get_pde 11132 <1> ; 11133 <1> pfh_um: ; Page fault handler for user/appl. mode (CPL=3) 11134 000026D1 8B1D[046D0000] <1> mov ebx, [u.pgdir] ; Page directory of current/active process 11135 <1> ; Physical address of the USER's page directory 11136 <1> ; Note: Lower 12 bits are 0. (page boundary) 11137 <1> pfh_get_pde: 11138 000026D7 80CA03 <1> or dl, 3 ; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT 11139 000026DA 0F20D1 <1> mov ecx, cr2 ; CR2 contains the virtual address 11140 <1> ; which has been caused to page fault 11141 <1> ; 11142 000026DD C1E914 <1> shr ecx, 20 ; shift 20 bits right 11143 000026E0 80E1FC <1> and cl, 0FCh ; mask lower 2 bits to get PDE offset 11144 <1> ; 11145 000026E3 01CB <1> add ebx, ecx ; now, EBX points to the relevant page dir entry 11146 000026E5 8B0B <1> mov ecx, [ebx] ; physical (base) address of the page table 11147 000026E7 F6C101 <1> test cl, 1 ; check bit 0 is set (1) or not (0). 11148 000026EA 741A <1> jz short pfh_set_pde ; Page directory entry is not valid, 11149 <1> ; set/validate page directory entry 11150 000026EC 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 11151 000026F1 89CB <1> mov ebx, ecx ; Physical address of the page table 11152 000026F3 89C1 <1> mov ecx, eax ; new page address (physical) 11153 000026F5 EB25 <1> jmp short pfh_get_pte 11154 <1> 11155 <1> ; 31/12/2021 (short jump) 11156 <1> pfh_im_err: 11157 000026F7 B8E4000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX 11158 <1> ; Major (Primary) Error: Page Fault 11159 <1> ; Minor (Secondary) Error: Insufficient Memory ! 11160 000026FC EB36 <1> jmp short pfh_err_retn 11161 <1> 11162 <1> ; 31/12/2021 11163 <1> pfh_p_err: ; 09/03/2015 11164 <1> pfh_pv_err: 11165 <1> ; Page fault was caused by a protection-violation 11166 000026FE B8E6000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX 11167 <1> ; Major (Primary) Error: Page Fault 11168 <1> ; Minor (Secondary) Error: Protection violation ! 11169 00002703 F9 <1> stc 11170 00002704 EB2E <1> jmp short pfh_err_retn 11171 <1> 11172 <1> pfh_set_pde: 11173 <1> ;; NOTE: Page directories and page tables never be swapped out! 11174 <1> ;; (So, we know this PDE is empty or invalid) 11175 <1> ; 11176 00002706 08D0 <1> or al, dl ; lower 3 bits are used as U/S, R/W, P flags 11177 00002708 8903 <1> mov [ebx], eax ; Let's put the new page directory entry here ! 11178 0000270A 30C0 <1> xor al, al ; clear lower (3..8) bits 11179 0000270C 89C3 <1> mov ebx, eax 11180 0000270E E8CCFCFFFF <1> call allocate_page ; (allocate a new page) 11181 00002713 72E2 <1> jc short pfh_im_err ; 'insufficient memory' error 11182 <1> pfh_spde_1: 11183 <1> ; EAX = Physical (base) address of the allocated (new) page 11184 00002715 89C1 <1> mov ecx, eax 11185 00002717 E834FDFFFF <1> call clear_page ; Clear page content 11186 <1> pfh_get_pte: 11187 0000271C 0F20D0 <1> mov eax, cr2 ; virtual address 11188 <1> ; which has been caused to page fault 11189 0000271F 89C7 <1> mov edi, eax ; 20/07/2015 11190 00002721 C1E80C <1> shr eax, 12 ; shift 12 bit right to get 11191 <1> ; higher 20 bits of the page fault address 11192 00002724 25FF030000 <1> and eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 11193 00002729 C1E002 <1> shl eax, 2 ; shift 2 bits left to get PTE offset 11194 0000272C 01C3 <1> add ebx, eax ; now, EBX points to the relevant page table entry 11195 <1> ; 17/04/2021 temporary 11196 <1> ; mov eax, [ebx] ; get previous value of pte 11197 <1> ; ; bit 0 of EAX is always 0 (otherwise we would not be here) 11198 <1> ; 17/04/2021 11199 <1> ; ('swap_in' procedure call has been disabled as temporary) 11200 <1> ; 11201 <1> ; and eax, eax 11202 <1> ; jz short pfh_gpte_1 11203 <1> ; ; 20/07/2015 11204 <1> ; xchg ebx, ecx ; new page address (physical) 11205 <1> ; push ebp ; 20/07/2015 11206 <1> ; mov ebp, cr2 11207 <1> ; ; ECX = physical address of the page table entry 11208 <1> ; ; EBX = Memory page address (physical!) 11209 <1> ; ; EAX = Swap disk (offset) address 11210 <1> ; ; EBP = virtual address (page fault address) 11211 <1> ; call swap_in 11212 <1> ; pop ebp 11213 <1> ; jc short pfh_err_retn 11214 <1> ; xchg ecx, ebx 11215 <1> ; ; EBX = physical address of the page table entry 11216 <1> ; ; ECX = new page 11217 <1> pfh_gpte_1: 11218 0000272E 08D1 <1> or cl, dl ; lower 3 bits are used as U/S, R/W, P flags 11219 00002730 890B <1> mov [ebx], ecx ; Let's put the new page table entry here ! 11220 <1> pfh_cpp_ok: 11221 <1> ; 17/04/2021 11222 <1> ; ('add_to_swap_queue' procedure call has been disabled as temporary) 11223 <1> ; 11224 <1> ; ; 20/07/2015 11225 <1> ; mov ebx, cr2 11226 <1> ; call add_to_swap_queue 11227 <1> ; 11228 <1> ; The new PTE (which contains the new page) will be added to 11229 <1> ; the swap queue, here. 11230 <1> ; (Later, if memory will become insufficient, 11231 <1> ; one page will be swapped out which is at the head of 11232 <1> ; the swap queue by using FIFO and access check methods.) 11233 <1> ; 11234 00002732 31C0 <1> xor eax, eax ; 0 11235 <1> ; 11236 <1> pfh_err_retn: 11237 00002734 59 <1> pop ecx 11238 00002735 5A <1> pop edx 11239 00002736 5B <1> pop ebx 11240 00002737 C3 <1> retn 11241 <1> 11242 <1> copy_page: 11243 <1> ; 17/07/2022 11244 <1> ; 16/04/2021 11245 <1> ; 19/04/2020 - Retro UNIX 386 v2 11246 <1> ; 22/09/2015 11247 <1> ; 21/09/2015 11248 <1> ; 19/09/2015 11249 <1> ; 07/09/2015 11250 <1> ; 31/08/2015 11251 <1> ; 20/07/2015 11252 <1> ; 05/05/2015 11253 <1> ; 03/05/2015 11254 <1> ; 18/04/2015 11255 <1> ; 12/04/2015 11256 <1> ; 30/10/2014 11257 <1> ; 18/10/2014 (Retro UNIX 386 v1 - beginning) 11258 <1> ; 11259 <1> ; INPUT -> 11260 <1> ; EBX = Virtual (linear) address of source page 11261 <1> ; (Page fault address) 11262 <1> ; OUTPUT -> 11263 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 11264 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 11265 <1> ; EAX = 0 (CF = 1) 11266 <1> ; if there is not a free page to be allocated 11267 <1> ; (page content of the source page will be copied 11268 <1> ; onto the target/new page) 11269 <1> ; 11270 <1> ; Modified Registers -> ecx, ebx (except EAX) 11271 <1> ; 11272 <1> 11273 <1> ; 19/04/2020 - Retro UNIX 386 v2 11274 <1> ; INPUT: 11275 <1> ; EBX = Virtual (linear) address of source page 11276 <1> ; (Page fault address) 11277 <1> ; OUTPUT: 11278 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 11279 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 11280 <1> ; EAX = 0 (CF = 1) 11281 <1> ; if there is not a free page to be allocated 11282 <1> ; (page content of the source page will be copied 11283 <1> ; onto the target/new page) 11284 <1> ; 11285 <1> ; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021 11286 <1> 11287 00002738 56 <1> push esi ; * 11288 00002739 57 <1> push edi ; ** 11289 <1> ; 16/04/2021 11290 <1> ; 19/04/2020 - Retro UNIX 386 v2 11291 <1> ;push ebx ; *** 11292 <1> ;push ecx ; **** 11293 0000273A 31F6 <1> xor esi, esi 11294 0000273C C1EB0C <1> shr ebx, 12 ; shift 12 bits right to get PDE & PTE numbers 11295 0000273F 89D9 <1> mov ecx, ebx ; save page fault address (as 12 bit shifted) 11296 00002741 C1EB08 <1> shr ebx, 8 ; shift 8 bits right and then 11297 00002744 80E3FC <1> and bl, 0FCh ; mask lower 2 bits to get PDE offset 11298 00002747 89DF <1> mov edi, ebx ; save it for the parent of current process 11299 00002749 031D[046D0000] <1> add ebx, [u.pgdir] ; EBX points to the relevant page dir entry 11300 0000274F 8B03 <1> mov eax, [ebx] ; physical (base) address of the page table 11301 00002751 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 11302 00002755 89CB <1> mov ebx, ecx ; (restore higher 20 bits of page fault address) 11303 00002757 81E3FF030000 <1> and ebx, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 11304 <1> ;shl bx, 2 ; shift 2 bits left to get PTE offset 11305 <1> ; 17/07/2022 11306 0000275D C1E302 <1> shl ebx, 2 11307 00002760 01C3 <1> add ebx, eax ; EBX points to the relevant page table entry 11308 <1> ; 07/09/2015 11309 00002762 66F7030002 <1> test word [ebx], PTE_DUPLICATED ; (Does current process share this 11310 <1> ; read only page as a child process?) 11311 00002767 7509 <1> jnz short cpp_0 ; yes 11312 00002769 8B0B <1> mov ecx, [ebx] ; PTE value 11313 0000276B 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 11314 00002770 EB31 <1> jmp short cpp_1 11315 <1> cpp_0: 11316 00002772 89FE <1> mov esi, edi 11317 00002774 0335[086D0000] <1> add esi, [u.ppgdir] ; the parent's page directory entry 11318 0000277A 8B06 <1> mov eax, [esi] ; physical (base) address of the page table 11319 0000277C 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 11320 00002780 89CE <1> mov esi, ecx ; (restore higher 20 bits of page fault address) 11321 00002782 81E6FF030000 <1> and esi, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 11322 <1> ;shl si, 2 ; shift 2 bits left to get PTE offset 11323 <1> ; 17/07/2022 11324 00002788 C1E602 <1> shl esi, 2 11325 0000278B 01C6 <1> add esi, eax ; EDX points to the relevant page table entry 11326 0000278D 8B0E <1> mov ecx, [esi] ; PTE value of the parent process 11327 <1> ; 21/09/2015 11328 0000278F 8B03 <1> mov eax, [ebx] ; PTE value of the child process 11329 00002791 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear page attributes 11330 <1> ; 11331 00002795 F6C101 <1> test cl, PTE_A_PRESENT ; is it a present/valid page ? 11332 00002798 7424 <1> jz short cpp_3 ; the parent's page is not same page 11333 <1> ; 11334 0000279A 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 11335 0000279F 39C8 <1> cmp eax, ecx ; Same page? 11336 000027A1 751B <1> jne short cpp_3 ; Parent page and child page are not same 11337 <1> ; Convert child's page to writable page 11338 <1> cpp_1: 11339 000027A3 E837FCFFFF <1> call allocate_page 11340 000027A8 721A <1> jc short cpp_4 ; 'insufficient memory' error 11341 000027AA 21F6 <1> and esi, esi ; check ESI is valid or not 11342 000027AC 7405 <1> jz short cpp_2 11343 <1> ; Convert read only page to writable page 11344 <1> ;(for the parent of the current process) 11345 <1> ;and word [esi], PTE_A_CLEAR ; 0F000h 11346 <1> ; 22/09/2015 11347 000027AE 890E <1> mov [esi], ecx 11348 000027B0 800E07 <1> or byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER 11349 <1> ; 1+2+4 = 7 11350 <1> cpp_2: 11351 000027B3 89C7 <1> mov edi, eax ; new page address of the child process 11352 <1> ; 07/09/2015 11353 000027B5 89CE <1> mov esi, ecx ; the page address of the parent process 11354 000027B7 B900040000 <1> mov ecx, PAGE_SIZE / 4 11355 000027BC F3A5 <1> rep movsd ; 31/08/2015 11356 <1> cpp_3: 11357 000027BE 0C07 <1> or al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7 11358 000027C0 8903 <1> mov [ebx], eax ; Update PTE 11359 000027C2 28C0 <1> sub al, al ; clear attributes 11360 <1> cpp_4: 11361 <1> ; 16/04/2021 11362 <1> ; 19/04/2020 - Retro UNIX 386 v2 11363 <1> ;pop ecx ; **** 11364 <1> ;pop ebx ; *** 11365 000027C4 5F <1> pop edi ; ** 11366 000027C5 5E <1> pop esi ; * 11367 000027C6 C3 <1> retn 11368 <1> 11369 <1> ;; 28/04/2015 11370 <1> ;; 24/10/2014 11371 <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning) 11372 <1> ;; SWAP_PAGE_QUEUE (4096 bytes) 11373 <1> ;; 11374 <1> ;; 0000 0001 0002 0003 .... 1020 1021 1022 1023 11375 <1> ;; +------+------+------+------+- -+------+------+------+------+ 11376 <1> ;; | pg1 | pg2 | pg3 | pg4 | .... |pg1021|pg1022|pg1023|pg1024| 11377 <1> ;; +------+------+------+------+- -+------+------+------+------+ 11378 <1> ;; 11379 <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue 11380 <1> ;; 11381 <1> ;; Method: 11382 <1> ;; Swap page queue is a list of allocated pages with physical 11383 <1> ;; addresses (system mode virtual adresses = physical addresses). 11384 <1> ;; It is used for 'swap_in' and 'swap_out' procedures. 11385 <1> ;; When a new page is being allocated, swap queue is updated 11386 <1> ;; by 'swap_queue_shift' procedure, header of the queue (offset 0) 11387 <1> ;; is checked for 'accessed' flag. If the 1st page on the queue 11388 <1> ;; is 'accessed' or 'read only', it is dropped from the list; 11389 <1> ;; other pages from the 2nd to the last (in [swpq_last]) shifted 11390 <1> ;; to head then the 2nd page becomes the 1st and '[swpq_last]' 11391 <1> ;; offset value becomes it's previous offset value - 4. 11392 <1> ;; If the 1st page of the swap page queue is not 'accessed' 11393 <1> ;; the queue/list is not shifted. 11394 <1> ;; After the queue/list shift, newly allocated page is added 11395 <1> ;; to the tail of the queue at the [swpq_count*4] position. 11396 <1> ;; But, if [swpq_count] > 1023, the newly allocated page 11397 <1> ;; will not be added to the tail of swap page queue. 11398 <1> ;; 11399 <1> ;; During 'swap_out' procedure, swap page queue is checked for 11400 <1> ;; the first non-accessed, writable page in the list, 11401 <1> ;; from the head to the tail. The list is shifted to left 11402 <1> ;; (to the head) till a non-accessed page will be found in the list. 11403 <1> ;; Then, this page is swapped out (to disk) and then it is dropped 11404 <1> ;; from the list by a final swap queue shift. [swpq_count] value 11405 <1> ;; is changed. If all pages on the queue' are 'accessed', 11406 <1> ;; 'insufficient memory' error will be returned ('swap_out' 11407 <1> ;; procedure will be failed)... 11408 <1> ;; 11409 <1> ;; Note: If the 1st page of the queue is an 'accessed' page, 11410 <1> ;; 'accessed' flag of the page will be reset (0) and that page 11411 <1> ;; (PTE) will be added to the tail of the queue after 11412 <1> ;; the check, if [swpq_count] < 1023. If [swpq_count] = 1024 11413 <1> ;; the queue will be rotated and the PTE in the head will be 11414 <1> ;; added to the tail after resetting 'accessed' bit. 11415 <1> ;; 11416 <1> ;; 11417 <1> ;; 11418 <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks) 11419 <1> ;; 11420 <1> ;; 00000000 00000004 00000008 0000000C ... size-8 size-4 11421 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 11422 <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) | 11423 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 11424 <1> ;; 11425 <1> ;; [swpd_next] = the first free block address in swapped page records 11426 <1> ;; for next free block search by 'swap_out' procedure. 11427 <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes) 11428 <1> ;; NOTE: max. possible swap disk size is 1024 GB 11429 <1> ;; (entire swap space must be accessed by using 11430 <1> ;; 31 bit offset address) 11431 <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space 11432 <1> ;; [swpd_start] = absolute/start address of the swap disk/file 11433 <1> ;; 0 for file, or beginning sector of the swap partition 11434 <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file 11435 <1> ;; 11436 <1> ;; 11437 <1> ;; Method: 11438 <1> ;; When the memory (ram) becomes insufficient, page allocation 11439 <1> ;; procedure swaps out a page from memory to the swap disk 11440 <1> ;; (partition) or swap file to get a new free page at the memory. 11441 <1> ;; Swapping out is performed by using swap page queue. 11442 <1> ;; 11443 <1> ;; Allocation block size of swap disk/file is equal to page size 11444 <1> ;; (4096 bytes). Swapping address (in sectors) is recorded 11445 <1> ;; into relevant page file entry as 31 bit physical (logical) 11446 <1> ;; offset address as 1 bit shifted to left for present flag (0). 11447 <1> ;; Swapped page address is between 1 and swap disk/file size - 4. 11448 <1> ;; Absolute physical (logical) address of the swapped page is 11449 <1> ;; calculated by adding offset value to the swap partition's 11450 <1> ;; start address. If the swap device (disk) is a virtual disk 11451 <1> ;; or it is a file, start address of the swap disk/volume is 0, 11452 <1> ;; and offset value is equal to absolute (physical or logical) 11453 <1> ;; address/position. (It has not to be ZERO if the swap partition 11454 <1> ;; is in a partitioned virtual hard disk.) 11455 <1> ;; 11456 <1> ;; Note: Swap addresses are always specified/declared in sectors, 11457 <1> ;; not in bytes or in blocks/zones/clusters (4096 bytes) as unit. 11458 <1> ;; 11459 <1> ;; Swap disk/file allocation is mapped via 'Swap Allocation Table' 11460 <1> ;; at memory as similar to 'Memory Allocation Table'. 11461 <1> ;; 11462 <1> ;; Every bit of Swap Allocation Table repsesents one swap block 11463 <1> ;; (equal to page size) respectively. Bit 0 of the S.A.T. byte 0 11464 <1> ;; is reserved for swap disk/file block 0 as descriptor block 11465 <1> ;; (also for compatibility with PTE). If bit value is ZERO, 11466 <1> ;; it means relevant (respective) block is in use, and, 11467 <1> ;; of course, if bit value is 1, it means relevant (respective) 11468 <1> ;; swap disk/file block is free. 11469 <1> ;; For example: bit 1 of the byte 128 repsesents block 1025 11470 <1> ;; (128*8+1) or sector (offset) 8200 on the swap disk or 11471 <1> ;; byte (offset/position) 4198400 in the swap file. 11472 <1> ;; 4GB swap space is represented via 128KB Swap Allocation Table. 11473 <1> ;; Initial layout of Swap Allocation Table is as follows: 11474 <1> ;; ------------------------------------------------------------ 11475 <1> ;; 0111111111111111111111111 .... 11111111111111111111111111111 11476 <1> ;; ------------------------------------------------------------ 11477 <1> ;; (0 is reserved block, 1s represent free blocks respectively.) 11478 <1> ;; (Note: Allocation cell/unit of the table is bit, not byte) 11479 <1> ;; 11480 <1> ;; .............................................................. 11481 <1> ;; 11482 <1> ;; 'swap_out' procedure checks 'free_swap_blocks' count at first, 11483 <1> ;; then it searches Swap Allocation Table if free count is not 11484 <1> ;; zero. From begining the [swpd_next] dword value, the first bit 11485 <1> ;; position with value of 1 on the table is converted to swap 11486 <1> ;; disk/file offset address, in sectors (not 4096 bytes block). 11487 <1> ;; 'ldrv_write' procedure is called with ldrv (logical drive 11488 <1> ;; number of physical swap disk or virtual swap disk) 11489 <1> ;; number, sector offset (not absolute sector -LBA- number), 11490 <1> ;; and sector count (8, 512*8 = 4096) and buffer adress 11491 <1> ;; (memory page). That will be a direct disk write procedure. 11492 <1> ;; (for preventing late memory allocation, significant waiting). 11493 <1> ;; If disk write procedure returns with error or free count of 11494 <1> ;; swap blocks is ZERO, 'swap_out' procedure will return with 11495 <1> ;; 'insufficient memory error' (cf=1). 11496 <1> ;; 11497 <1> ;; (Note: Even if free swap disk/file blocks was not zero, 11498 <1> ;; any disk write error will not be fixed by 'swap_out' procedure, 11499 <1> ;; in other words, 'swap_out' will not check the table for other 11500 <1> ;; free blocks after a disk write error. It will return to 11501 <1> ;; the caller with error (CF=1) which means swapping is failed. 11502 <1> ;; 11503 <1> ;; After writing the page on to swap disk/file address/sector, 11504 <1> ;; 'swap_out' procedure returns with that swap (offset) sector 11505 <1> ;; address (cf=0). 11506 <1> ;; 11507 <1> ;; .............................................................. 11508 <1> ;; 11509 <1> ;; 'swap_in' procedure loads addressed (relevant) swap disk or 11510 <1> ;; file sectors at specified memory page. Then page allocation 11511 <1> ;; procedure updates relevant page table entry with 'present' 11512 <1> ;; attribute. If swap disk or file reading fails there is nothing 11513 <1> ;; to do, except to terminate the process which is the owner of 11514 <1> ;; the swapped page. 11515 <1> ;; 11516 <1> ;; 'swap_in' procedure sets the relevant/respective bit value 11517 <1> ;; in the Swap Allocation Table (as free block). 'swap_in' also 11518 <1> ;; updates [swpd_first] pointer if it is required. 11519 <1> ;; 11520 <1> ;; .............................................................. 11521 <1> ;; 11522 <1> ;; Note: If [swap_enabled] value is ZERO, that means there is not 11523 <1> ;; a swap disk or swap file in use... 'swap_in' and 'swap_out' 11524 <1> ;; procedures ans 'swap page que' procedures will not be active... 11525 <1> ;; 'Insufficient memory' error will be returned by 'swap_out' 11526 <1> ;; and 'general protection fault' will be returned by 'swap_in' 11527 <1> ;; procedure, if it is called mistakenly (a wrong value in a PTE). 11528 <1> ;; 11529 <1> 11530 <1> ; 17/04/2021 11531 <1> ; ('swap_in' procedure call is disabled as temporary) 11532 <1> 11533 <1> ; 30/11/2021 - temporary ! 11534 <1> ;swap_in: 11535 <1> ; 31/08/2015 11536 <1> ; 20/07/2015 11537 <1> ; 28/04/2015 11538 <1> ; 18/04/2015 11539 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 11540 <1> ; 11541 <1> ; INPUT -> 11542 <1> ; EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE 11543 <1> ; EBP = VIRTUAL (LINEAR) ADDRESS (page fault address) 11544 <1> ; EAX = Offset Address for the swapped page on the 11545 <1> ; swap disk or in the swap file. 11546 <1> ; 11547 <1> ; OUTPUT -> 11548 <1> ; EAX = 0 if loading at memory has been successful 11549 <1> ; 11550 <1> ; CF = 1 -> swap disk reading error (disk/file not present 11551 <1> ; or sector not present or drive not ready 11552 <1> ; EAX = Error code 11553 <1> ; [u.error] = EAX 11554 <1> ; = The last error code for the process 11555 <1> ; (will be reset after returning to user) 11556 <1> ; 11557 <1> ; Modified Registers -> EAX 11558 <1> ; 11559 <1> 11560 <1> ; cmp dword [swp_drv], 0 11561 <1> ; jna short swpin_dnp_err 11562 <1> ; 11563 <1> ; cmp eax, [swpd_size] 11564 <1> ; jnb short swpin_snp_err 11565 <1> ; 11566 <1> ; push esi 11567 <1> ; push ebx 11568 <1> ; push ecx 11569 <1> ; mov esi, [swp_drv] 11570 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 11571 <1> ; ; Note: Even if corresponding physical disk's sector 11572 <1> ; ; size different than 512 bytes, logical disk sector 11573 <1> ; ; size is 512 bytes and disk reading procedure 11574 <1> ; ; will be performed for reading 4096 bytes 11575 <1> ; ; (2*2048, 8*512). 11576 <1> ; ; ESI = Logical disk description table address 11577 <1> ; ; EBX = Memory page (buffer) address (physical!) 11578 <1> ; ; EAX = Sector adress (offset address, logical sector number) 11579 <1> ; ; ECX = Sector count ; 8 sectors 11580 <1> ; push eax 11581 <1> ; call logical_disk_read 11582 <1> ; pop eax 11583 <1> ; jnc short swpin_read_ok 11584 <1> ; ; 11585 <1> ; mov eax, SWP_DISK_READ_ERR ; drive not ready or read error 11586 <1> ; mov [u.error], eax 11587 <1> ; jmp short swpin_retn 11588 <1> ; ; 11589 <1> ;swpin_read_ok: 11590 <1> ; ; EAX = Offset address (logical sector number) 11591 <1> ; call unlink_swap_block ; Deallocate swap block 11592 <1> ; ; 11593 <1> ; ; EBX = Memory page (buffer) address (physical!) 11594 <1> ; ; 20/07/2015 11595 <1> ; mov ebx, ebp ; virtual address (page fault address) 11596 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 11597 <1> ; mov bl, [u.uno] ; current process number 11598 <1> ; ; EBX = Virtual (Linear) address & process number combination 11599 <1> ; call swap_queue_shift 11600 <1> ; ; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0) 11601 <1> ; ;sub eax, eax ; 0 ; Error Code = 0 (no error) 11602 <1> ; ; zf = 1 11603 <1> ;swpin_retn: 11604 <1> ; pop ecx 11605 <1> ; pop ebx 11606 <1> ; pop esi 11607 <1> ; retn 11608 <1> ; 11609 <1> ;swpin_dnp_err: 11610 <1> ; mov eax, SWP_DISK_NOT_PRESENT_ERR 11611 <1> ;swpin_err_retn: 11612 <1> ; mov [u.error], eax 11613 <1> ; stc 11614 <1> ; retn 11615 <1> ; 11616 <1> ;swpin_snp_err: 11617 <1> ; mov eax, SWP_SECTOR_NOT_PRESENT_ERR 11618 <1> ; jmp short swpin_err_retn 11619 <1> 11620 <1> ; 17/04/2021 11621 <1> ; ('swap_out' procedure call is disabled as temporary) 11622 <1> 11623 <1> ; 30/11/2021 - temporary ! 11624 <1> ;swap_out: 11625 <1> ; 10/06/2016 11626 <1> ; 07/06/2016 11627 <1> ; 23/05/2016 11628 <1> ; 19/05/2016 - TRDOS 386 (TRDOS v2.0) 11629 <1> ; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1) 11630 <1> ; 11631 <1> ; INPUT -> 11632 <1> ; none 11633 <1> ; 11634 <1> ; OUTPUT -> 11635 <1> ; EAX = Physical page address (which is swapped out 11636 <1> ; for allocating a new page) 11637 <1> ; CF = 1 -> swap disk writing error (disk/file not present 11638 <1> ; or sector not present or drive not ready 11639 <1> ; EAX = Error code 11640 <1> ; [u.error] = EAX 11641 <1> ; = The last error code for the process 11642 <1> ; (will be reset after returning to user) 11643 <1> ; 11644 <1> ; Modified Registers -> none (except EAX) 11645 <1> ; 11646 <1> 11647 <1> ; cmp word [swpq_count], 1 11648 <1> ; jc swpout_im_err ; 'insufficient memory' 11649 <1> ; 11650 <1> ; ;cmp dword [swp_drv], 1 11651 <1> ; ;jc short swpout_dnp_err ; 'swap disk/file not present' 11652 <1> ; 11653 <1> ; cmp dword [swpd_free], 1 11654 <1> ; jc swpout_nfspc_err ; 'no free space on swap disk' 11655 <1> ; 11656 <1> ; push ebx ; * 11657 <1> ;swpout_1: 11658 <1> ; ; 10/06/2016 11659 <1> ; xor ebx, ebx ; shift the queue and return a PTE value 11660 <1> ; call swap_queue_shift 11661 <1> ; and eax, eax ; 0 = empty queue (improper entries) 11662 <1> ; jz swpout_npts_err ; There is not any proper PTE 11663 <1> ; ; pointer in the swap queue 11664 <1> ; ; EAX = PTE value of the page 11665 <1> ; ; EBX = PTE address of the page 11666 <1> ; and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 11667 <1> ; ; 11668 <1> ; ; 07/06/2016 11669 <1> ; ; 19/05/2016 11670 <1> ; ; check this page is in timer events or not 11671 <1> ; 11672 <1> ;swpout_timer_page_0: 11673 <1> ; push edx ; ** 11674 <1> ; 11675 <1> ; ; 07/06/2016 11676 <1> ; cmp byte [timer_events], 0 11677 <1> ; jna short swpout_2 11678 <1> ; ; 11679 <1> ; mov dl, [timer_events] 11680 <1> ; 11681 <1> ; push ecx ; *** 11682 <1> ; push ebx ; **** 11683 <1> ; mov ebx, timer_set ; beginning address of timer event 11684 <1> ; ; structures 11685 <1> ;swpout_timer_page_1: 11686 <1> ; mov cl, [ebx] 11687 <1> ; or cl, cl ; 0 = free, >0 = process number 11688 <1> ; jz short swpout_timer_page_3 11689 <1> ; mov ecx, [ebx+12] ; response (signal return) address 11690 <1> ; and cx, PTE_A_CLEAR ; clear offset part (right 12 bits) 11691 <1> ; ; of the response byte address, to 11692 <1> ; ; get beginning of the page address) 11693 <1> ; cmp eax, ecx 11694 <1> ; jne short swpout_timer_page_2 ; not same page 11695 <1> ; 11696 <1> ; ; !same page! 11697 <1> ; ; 11698 <1> ; ; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! - 11699 <1> ; ; This page will be used by the kernel to put timer event 11700 <1> ; ; response (signal return) byte at the requested address; 11701 <1> ; ; in order to prevent a possible wrong write (while 11702 <1> ; ; this page is swapped out) on physical memory, 11703 <1> ; ; we must protect this page against to be swapped out! 11704 <1> ; ; 11705 <1> ; pop ebx ; **** 11706 <1> ; pop ecx ; *** 11707 <1> ; pop edx ; ** 11708 <1> ; jmp short swpout_1 ; do not swap out this page ! 11709 <1> ; 11710 <1> ;swpout_timer_page_2: 11711 <1> ; ; 07/06/2016 11712 <1> ; dec dl 11713 <1> ; jz short swpout_timer_page_4 11714 <1> ;swpout_timer_page_3: 11715 <1> ; ;cmp ebx, timer_set + 240 ; last timer event (15*16) 11716 <1> ; ;jnb short swpout_timer_page_4 11717 <1> ; add ebx, 16 11718 <1> ; jmp short swpout_timer_page_1 11719 <1> ; 11720 <1> ;swpout_timer_page_4: 11721 <1> ; pop ebx ; **** 11722 <1> ; pop ecx ; *** 11723 <1> ;swpout_2: 11724 <1> ; mov edx, ebx ; Page table entry address 11725 <1> ; mov ebx, eax ; Buffer (Page) Address 11726 <1> ; ; 11727 <1> ; call link_swap_block 11728 <1> ; jnc short swpout_3 ; It may not be needed here 11729 <1> ; ; because [swpd_free] value 11730 <1> ; ; was checked at the beginging. 11731 <1> ; pop edx ; ** 11732 <1> ; pop ebx ; * 11733 <1> ; jmp short swpout_nfspc_err 11734 <1> ;swpout_3: 11735 <1> ; test eax, 80000000h ; test bit 31 (this may not be needed!) 11736 <1> ; jnz short swpout_nfspc_err ; 10/06/2016 (bit 31 = 1 !) 11737 <1> ; ; 11738 <1> ; push esi ; ** 11739 <1> ; push ecx ; *** 11740 <1> ; push eax ; sector address ; (31 bit !, bit 31 = 0) 11741 <1> ; mov esi, [swp_drv] 11742 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 11743 <1> ; ; Note: Even if corresponding physical disk's sector 11744 <1> ; ; size different than 512 bytes, logical disk sector 11745 <1> ; ; size is 512 bytes and disk writing procedure 11746 <1> ; ; will be performed for writing 4096 bytes 11747 <1> ; ; (2*2048, 8*512). 11748 <1> ; ; ESI = Logical disk description table address 11749 <1> ; ; EBX = Buffer (Page) address 11750 <1> ; ; EAX = Sector adress (offset address, logical sector number) 11751 <1> ; ; ECX = Sector count ; 8 sectors 11752 <1> ; ; edx = PTE address 11753 <1> ; call logical_disk_write 11754 <1> ; ; edx = PTE address 11755 <1> ; pop ecx ; sector address 11756 <1> ; jnc short swpout_write_ok 11757 <1> ; ; 11758 <1> ; ;; call unlink_swap_block ; this block must be left as 'in use' 11759 <1> ;swpout_dw_err: 11760 <1> ; mov eax, SWP_DISK_WRITE_ERR ; drive not ready or write error 11761 <1> ; mov [u.error], eax 11762 <1> ; jmp short swpout_retn 11763 <1> ; ; 11764 <1> ;swpout_write_ok: 11765 <1> ; ; EBX = Buffer (page) address 11766 <1> ; ; EDX = Page Table Entry address 11767 <1> ; ; ECX = Swap disk sector (file block) address (31 bit) 11768 <1> ; shl ecx, 1 ; 31 bit sector address from bit 1 to bit 31 11769 <1> ; mov [edx], ecx 11770 <1> ; ; bit 0 = 0 (swapped page) 11771 <1> ; mov eax, ebx 11772 <1> ;swpout_retn: 11773 <1> ; pop ecx ; *** 11774 <1> ; pop esi ; ** 11775 <1> ; pop ebx ; * 11776 <1> ; retn 11777 <1> ; 11778 <1> ;;swpout_dnp_err: 11779 <1> ;; mov eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present 11780 <1> ;; jmp short swpout_err_retn 11781 <1> ;swpout_nfspc_err: 11782 <1> ; mov eax, SWP_NO_FREE_SPACE_ERR ; no free space 11783 <1> ;swpout_err_retn: 11784 <1> ; mov [u.error], eax 11785 <1> ; ;stc 11786 <1> ; retn 11787 <1> ;swpout_npts_err: 11788 <1> ; mov eax, SWP_NO_PAGE_TO_SWAP_ERR 11789 <1> ; pop ebx 11790 <1> ; jmp short swpout_err_retn 11791 <1> ;swpout_im_err: 11792 <1> ; mov eax, ERR_MINOR_IM ; insufficient (out of) memory 11793 <1> ; jmp short swpout_err_retn 11794 <1> 11795 <1> ; 17/04/2021 11796 <1> ; ('swap_queue_shift' procedure call is disabled as temporary) 11797 <1> 11798 <1> ; 30/11/2021 - temporary ! 11799 <1> ;swap_queue_shift: 11800 <1> ; 26/03/2017 11801 <1> ; 10/06/2016 11802 <1> ; 09/06/2016 - TRDOS 386 (TRDOS v2.0) 11803 <1> ; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1) 11804 <1> ; 11805 <1> ; INPUT -> 11806 <1> ; EBX = Virtual (linear) address (bit 12 to 31) 11807 <1> ; and process number combination (bit 0 to 11) 11808 <1> ; EBX = 0 -> shift/drop from the head (offset 0) 11809 <1> ; 11810 <1> ; OUTPUT -> 11811 <1> ; If EBX input > 0 11812 <1> ; the queue will be shifted 4 bytes (dword), 11813 <1> ; from the tail to the head, up to entry offset 11814 <1> ; which points to EBX input value or nothing 11815 <1> ; to do if EBX value is not found on the queue. 11816 <1> ; (The entry -with EBX value- will be removed 11817 <1> ; from the queue if it is found.) 11818 <1> ; 11819 <1> ; EAX = 0 11820 <1> ; 11821 <1> ; If EBX input = 0 11822 <1> ; the queue will be shifted 4 bytes (dword), 11823 <1> ; from the tail to the head, if the PTE address 11824 <1> ; which is pointed in head of the queue is marked 11825 <1> ; as "accessed" or it is marked as "non present". 11826 <1> ; (If "accessed" flag of the PTE -which is pointed 11827 <1> ; in the head- is set -to 1-, it will be reset 11828 <1> ; -to 0- and then, the queue will be rotated 11829 <1> ; -without dropping pointer of the PTE from 11830 <1> ; the queue- for 4 bytes on head to tail direction. 11831 <1> ; Pointer in the head will be moved into the tail, 11832 <1> ; other PTEs will be shifted on head direction.) 11833 <1> ; 11834 <1> ; Swap queue will be shifted up to the first 11835 <1> ; 'present' or 'non accessed' page will be found 11836 <1> ; (as pointed) on the queue head (then it will be 11837 <1> ; removed/dropped from the queue). 11838 <1> ; 11839 <1> ; EAX (> 0) = PTE value of the page which is 11840 <1> ; (it's pointer -virtual address-) dropped 11841 <1> ; (removed) from swap queue. 11842 <1> ; EBX = PTE address of the page (if EAX > 0) 11843 <1> ; which is (it's pointer -virtual address-) 11844 <1> ; dropped (removed) from swap queue. 11845 <1> ; 11846 <1> ; EAX = 0 -> empty swap queue ! 11847 <1> ; 11848 <1> ; Modified Registers -> EAX, EBX 11849 <1> ; 11850 <1> ; movzx eax, word [swpq_count] ; Max. 1024 11851 <1> ; and ax, ax 11852 <1> ; jz short swpqs_retn 11853 <1> ; push edi 11854 <1> ; push esi 11855 <1> ; push ecx 11856 <1> ; mov esi, swap_queue 11857 <1> ; mov ecx, eax 11858 <1> ; or ebx, ebx 11859 <1> ; jz short swpqs_7 11860 <1> ;swpqs_1: 11861 <1> ; lodsd 11862 <1> ; cmp eax, ebx 11863 <1> ; je short swpqs_2 11864 <1> ; loop swpqs_1 11865 <1> ; ; 10/06/2016 11866 <1> ; sub eax, eax 11867 <1> ; jmp short swpqs_6 11868 <1> ;swpqs_2: 11869 <1> ; mov edi, esi 11870 <1> ; sub edi, 4 11871 <1> ;swpqs_3: 11872 <1> ; dec word [swpq_count] 11873 <1> ; jz short swpqs_5 11874 <1> ;swpqs_4: 11875 <1> ; dec ecx 11876 <1> ; rep movsd ; shift up (to the head) 11877 <1> ;swpqs_5: 11878 <1> ; xor eax, eax 11879 <1> ; mov [edi], eax 11880 <1> ;swpqs_6: 11881 <1> ; pop ecx 11882 <1> ; pop esi 11883 <1> ; pop edi 11884 <1> ;swpqs_retn: 11885 <1> ; retn 11886 <1> ;swpqs_7: 11887 <1> ; mov edi, esi ; head 11888 <1> ; lodsd 11889 <1> ; ; 20/07/2015 11890 <1> ; mov ebx, eax 11891 <1> ; and ebx, ~PAGE_OFF ; ~0FFFh 11892 <1> ; ; ebx = virtual address (at page boundary) 11893 <1> ; and eax, PAGE_OFF ; 0FFFh 11894 <1> ; ; ax = process number (1 to 4095) 11895 <1> ; cmp al, [u.uno] 11896 <1> ; ; Max. 16 (nproc) processes for Retro UNIX 386 v1 11897 <1> ; jne short swpqs_8 11898 <1> ; mov eax, [u.pgdir] 11899 <1> ; jmp short swpqs_9 11900 <1> ;swpqs_8: 11901 <1> ; ; 09/06/2016 11902 <1> ; cmp byte [eax+p.stat-1], 0 11903 <1> ; jna short swpqs_3 ; free (or terminated) process 11904 <1> ; cmp byte [eax+p.stat-1], 2 ; waiting 11905 <1> ; ja short swpqs_3 ; zombie (3) or undefined ? 11906 <1> ; 11907 <1> ; ;shl ax, 2 11908 <1> ; shl al, 2 11909 <1> ; mov eax, [eax+p.upage-4] 11910 <1> ; or eax, eax 11911 <1> ; jz short swpqs_3 ; invalid upage 11912 <1> ; add eax, u.pgdir - user 11913 <1> ; ; u.pgdir value for the process 11914 <1> ; ; is in [eax] 11915 <1> ; mov eax, [eax] 11916 <1> ; and eax, eax 11917 <1> ; jz short swpqs_3 ; invalid page directory 11918 <1> ;swpqs_9: 11919 <1> ; push edx 11920 <1> ; ; eax = page directory 11921 <1> ; ; ebx = virtual address 11922 <1> ; call get_pte 11923 <1> ; mov ebx, edx ; PTE address 11924 <1> ; pop edx 11925 <1> ; ; 10/06/2016 11926 <1> ; jc short swpqs_13 ; empty PDE 11927 <1> ; ; EAX = PTE value 11928 <1> ; test al, PTE_A_PRESENT ; bit 0 = 1 11929 <1> ; jz short swpqs_13 ; Drop non-present page 11930 <1> ; ; from the queue (head) 11931 <1> ; test al, PTE_A_WRITE ; bit 1 = 0 (read only) 11932 <1> ; jz short swpqs_13 ; Drop read only page 11933 <1> ; ; from the queue (head) 11934 <1> ; ;test al, PTE_A_ACCESS ; bit 5 = 1 (Accessed) 11935 <1> ; ;jnz short swpqs_11 ; present 11936 <1> ; ; accessed page 11937 <1> ; btr eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit 11938 <1> ; jc short swpqs_11 ; accessed page 11939 <1> ; 11940 <1> ; dec ecx 11941 <1> ; mov [swpq_count], cx 11942 <1> ; jz short swpqs_10 11943 <1> ; ; esi = head + 4 11944 <1> ; ; edi = head 11945 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 11946 <1> ;swpqs_10: 11947 <1> ; mov [edi], ecx ; 0 11948 <1> ; jmp short swpqs_6 ; 26/03/2017 11949 <1> ; 11950 <1> ;swpqs_11: 11951 <1> ; mov [ebx], eax ; save changed attribute 11952 <1> ; ; Rotation (head -> tail) 11953 <1> ; dec ecx ; entry count -> last entry number 11954 <1> ; jz short swpqs_10 11955 <1> ; ; esi = head + 4 11956 <1> ; ; edi = head 11957 <1> ; mov eax, [edi] ; 20/07/2015 11958 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 11959 <1> ; mov [edi], eax ; head -> tail ; [k] = [1] 11960 <1> ; 11961 <1> ; mov cx, [swpq_count] 11962 <1> ; 11963 <1> ;swpqs_12: 11964 <1> ; mov esi, swap_queue ; head 11965 <1> ; jmp swpqs_7 11966 <1> ; 11967 <1> ;swpqs_13: 11968 <1> ; dec ecx 11969 <1> ; mov [swpq_count], cx 11970 <1> ; jz swpqs_5 11971 <1> ; jmp short swpqs_12 11972 <1> 11973 <1> ; 17/04/2021 11974 <1> ; ('add_to_swp_queue' procedure call is disabled as temporary) 11975 <1> 11976 <1> ; 30/11/2021 - temporary ! 11977 <1> ;add_to_swap_queue: 11978 <1> ; 20/02/2017 11979 <1> ; 20/07/2015 11980 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 11981 <1> ; 11982 <1> ; Adds new page to swap queue 11983 <1> ; (page directories and page tables must not be added 11984 <1> ; to swap queue) 11985 <1> ; 11986 <1> ; INPUT -> 11987 <1> ; EBX = Linear (Virtual) addr for current process 11988 <1> ; [u.uno] 11989 <1> ; 20/02/2017 11990 <1> ; (Linear address = CORE + user's virtual address) 11991 <1> ; 11992 <1> ; OUTPUT -> 11993 <1> ; EAX = [swpq_count] 11994 <1> ; (after the PTE has been added) 11995 <1> ; EAX = 0 -> Swap queue is full, (1024 entries) 11996 <1> ; the PTE could not be added. 11997 <1> ; 11998 <1> ; Modified Registers -> EAX 11999 <1> ; 12000 <1> ; push ebx 12001 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 12002 <1> ; mov bl, [u.uno] ; current process number 12003 <1> ; call swap_queue_shift ; drop from the queue if 12004 <1> ; ; it is already on the queue 12005 <1> ; ; then add it to the tail of the queue 12006 <1> ; movzx eax, word [swpq_count] 12007 <1> ; cmp ax, 1024 12008 <1> ; jb short atsq_1 12009 <1> ; sub ax, ax 12010 <1> ; pop ebx 12011 <1> ; retn 12012 <1> ;atsq_1: 12013 <1> ; push esi 12014 <1> ; mov esi, swap_queue 12015 <1> ; and ax, ax 12016 <1> ; jz short atsq_2 12017 <1> ; shl ax, 2 ; convert to offset 12018 <1> ; add esi, eax 12019 <1> ; shr ax, 2 12020 <1> ;atsq_2: 12021 <1> ; inc ax 12022 <1> ; mov [esi], ebx ; Virtual address + [u.uno] combination 12023 <1> ; mov [swpq_count], ax 12024 <1> ; pop esi 12025 <1> ; pop ebx 12026 <1> ; retn 12027 <1> 12028 <1> ; 17/04/2021 12029 <1> ; ('unlink_swap_block' procedure call is disabled as temporary) 12030 <1> 12031 <1> ; 30/11/2021 - temporary ! 12032 <1> ;unlink_swap_block: 12033 <1> ; 15/09/2015 12034 <1> ; 30/04/2015 12035 <1> ; 18/04/2015 12036 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 12037 <1> ; 12038 <1> ; INPUT -> 12039 <1> ; EAX = swap disk/file offset address 12040 <1> ; (bit 1 to bit 31) 12041 <1> ; OUTPUT -> 12042 <1> ; [swpd_free] is increased 12043 <1> ; (corresponding SWAP DISK ALLOC. TABLE bit is SET) 12044 <1> ; 12045 <1> ; Modified Registers -> EAX 12046 <1> ; 12047 <1> ; push ebx 12048 <1> ; push edx 12049 <1> ; ; 12050 <1> ; shr eax, SECTOR_SHIFT+1 ;3+1 ; shift sector address to 12051 <1> ; ; 3 bits right 12052 <1> ; ; to get swap block/page number 12053 <1> ; mov edx, eax 12054 <1> ; ; 15/09/2015 12055 <1> ; shr edx, 3 ; to get offset to S.A.T. 12056 <1> ; ; (1 allocation bit = 1 page) 12057 <1> ; ; (1 allocation bytes = 8 pages) 12058 <1> ; and dl, 0FCh ; clear lower 2 bits 12059 <1> ; ; (to get 32 bit position) 12060 <1> ; ; 12061 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table address 12062 <1> ; add ebx, edx 12063 <1> ; and eax, 1Fh ; lower 5 bits only 12064 <1> ; ; (allocation bit position) 12065 <1> ; cmp eax, [swpd_next] ; is the new free block addr. lower 12066 <1> ; ; than the address in 'swpd_next' ? 12067 <1> ; ; (next/first free block value) 12068 <1> ; jnb short uswpbl_1 ; no 12069 <1> ; mov [swpd_next], eax ; yes 12070 <1> ;uswpbl_1: 12071 <1> ; bts [ebx], eax ; unlink/release/deallocate block 12072 <1> ; ; set relevant bit to 1. 12073 <1> ; ; set CF to the previous bit value 12074 <1> ; cmc ; complement carry flag 12075 <1> ; jc short uswpbl_2 ; do not increase swfd_free count 12076 <1> ; ; if the block is already deallocated 12077 <1> ; ; before. 12078 <1> ; inc dword [swpd_free] 12079 <1> ;uswpbl_2: 12080 <1> ; pop edx 12081 <1> ; pop ebx 12082 <1> ; retn 12083 <1> 12084 <1> ; 17/04/2021 12085 <1> ; ('link_swap_block' procedure call is disabled as temporary) 12086 <1> 12087 <1> ; 30/11/2021 - temporary ! 12088 <1> ;link_swap_block: 12089 <1> ; 01/07/2015 12090 <1> ; 18/04/2015 12091 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 12092 <1> ; 12093 <1> ; INPUT -> none 12094 <1> ; 12095 <1> ; OUTPUT -> 12096 <1> ; EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes) 12097 <1> ; in sectors (corresponding 12098 <1> ; SWAP DISK ALLOCATION TABLE bit is RESET) 12099 <1> ; 12100 <1> ; CF = 1 and EAX = 0 12101 <1> ; if there is not a free block to be allocated 12102 <1> ; 12103 <1> ; Modified Registers -> none (except EAX) 12104 <1> ; 12105 <1> 12106 <1> ; ;mov eax, [swpd_free] 12107 <1> ; ;and eax, eax 12108 <1> ; ;jz short out_of_swpspc 12109 <1> ; ; 12110 <1> ; push ebx 12111 <1> ; push ecx 12112 <1> ; ; 12113 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table offset 12114 <1> ; mov ecx, ebx 12115 <1> ; add ebx, [swpd_next] ; Free block searching starts from here 12116 <1> ; ; next_free_swap_block >> 5 12117 <1> ; add ecx, [swpd_last] ; Free block searching ends here 12118 <1> ; ; (total_swap_blocks - 1) >> 5 12119 <1> ;lswbl_scan: 12120 <1> ; cmp ebx, ecx 12121 <1> ; ja short lswbl_notfound 12122 <1> ; ; 12123 <1> ; bsf eax, [ebx] ; Scans source operand for first bit set (1). 12124 <1> ; ; Clears ZF if a bit is found set (1) and 12125 <1> ; ; loads the destination with an index to 12126 <1> ; ; first set bit. (0 -> 31) 12127 <1> ; ; Sets ZF to 1 if no bits are found set. 12128 <1> ; ; 01/07/2015 12129 <1> ; jnz short lswbl_found ; ZF = 0 -> a free block has been found 12130 <1> ; ; 12131 <1> ; ; NOTE: a Swap Disk Allocation Table bit 12132 <1> ; ; with value of 1 means 12133 <1> ; ; the corresponding page is free 12134 <1> ; ; (Retro UNIX 386 v1 feaure only!) 12135 <1> ; add ebx, 4 12136 <1> ; ; We return back for searching next page block 12137 <1> ; ; NOTE: [swpd_free] is not ZERO; so, 12138 <1> ; ; we always will find at least 1 free block here. 12139 <1> ; jmp short lswbl_scan 12140 <1> ; ; 12141 <1> ;lswbl_notfound: 12142 <1> ; sub ecx, swap_alloc_table 12143 <1> ; mov [swpd_next], ecx ; next/first free page = last page 12144 <1> ; ; (unlink_swap_block procedure will change it) 12145 <1> ; xor eax, eax 12146 <1> ; mov [swpd_free], eax 12147 <1> ; stc 12148 <1> ;lswbl_ok: 12149 <1> ; pop ecx 12150 <1> ; pop ebx 12151 <1> ; retn 12152 <1> ; ; 12153 <1> ;;out_of_swpspc: 12154 <1> ;; stc 12155 <1> ;; retn 12156 <1> ; 12157 <1> ;lswbl_found: 12158 <1> ; mov ecx, ebx 12159 <1> ; sub ecx, swap_alloc_table 12160 <1> ; mov [swpd_next], ecx ; Set first free block searching start 12161 <1> ; ; address/offset (to the next) 12162 <1> ; dec dword [swpd_free] ; 1 block has been allocated (X = X-1) 12163 <1> ; ; 12164 <1> ; btr [ebx], eax ; The destination bit indexed by the source value 12165 <1> ; ; is copied into the Carry Flag and then cleared 12166 <1> ; ; in the destination. 12167 <1> ; ; 12168 <1> ; ; Reset the bit which is corresponding to the 12169 <1> ; ; (just) allocated block. 12170 <1> ; shl ecx, 5 ; (block offset * 32) + block index 12171 <1> ; add eax, ecx ; = block number 12172 <1> ; shl eax, SECTOR_SHIFT ; 3, sector (offset) address of the block 12173 <1> ; ; 1 block = 8 sectors 12174 <1> ; ; 12175 <1> ; ; EAX = offset address of swap disk/file sector (beginning of the block) 12176 <1> ; ; 12177 <1> ; ; NOTE: The relevant page table entry will be updated 12178 <1> ; ; according to this EAX value... 12179 <1> ; ; 12180 <1> ; jmp short lswbl_ok 12181 <1> 12182 <1> ; 17/04/2021 12183 <1> ; ('logical_disk_read' procedure call is disabled as temporary) 12184 <1> 12185 <1> ; 30/11/2021 - temporary ! 12186 <1> ;logical_disk_read: 12187 <1> ; 20/07/2015 12188 <1> ; 09/03/2015 (temporary code here) 12189 <1> ; 12190 <1> ; INPUT -> 12191 <1> ; ESI = Logical disk description table address 12192 <1> ; EBX = Memory page (buffer) address (physical!) 12193 <1> ; EAX = Sector adress (offset address, logical sector number) 12194 <1> ; ECX = Sector count 12195 <1> ; 12196 <1> ; 12197 <1> ; retn 12198 <1> 12199 <1> ; 17/04/2021 12200 <1> ; ('logical_disk_write' procedure call is disabled as temporary) 12201 <1> 12202 <1> ; 30/11/2021 - temporary ! 12203 <1> ;logical_disk_write: 12204 <1> ; 20/07/2015 12205 <1> ; 09/03/2015 (temporary code here) 12206 <1> ; 12207 <1> ; INPUT -> 12208 <1> ; ESI = Logical disk description table address 12209 <1> ; EBX = Memory page (buffer) address (physical!) 12210 <1> ; EAX = Sector adress (offset address, logical sector number) 12211 <1> ; ECX = Sector count 12212 <1> ; 12213 <1> ; retn 12214 <1> 12215 <1> get_physical_addr: 12216 <1> ; 17/04/2021 - Retro UNIX 386 v2 12217 <1> ; (temporary modifications) 12218 <1> ; 19/04/2020 - Retro UNIX 386 v2 12219 <1> ; 18/10/2015 12220 <1> ; 29/07/2015 12221 <1> ; 20/07/2015 12222 <1> ; 04/06/2015 12223 <1> ; 20/05/2015 12224 <1> ; 28/04/2015 12225 <1> ; 18/04/2015 12226 <1> ; Get physical address 12227 <1> ; (allocates a new page for user if it is not present) 12228 <1> ; 12229 <1> ; (This subroutine is needed for mapping user's virtual 12230 <1> ; (buffer) address to physical address (of the buffer).) 12231 <1> ; ('sys write', 'sys read' system calls...) 12232 <1> ; 12233 <1> ; INPUT -> 12234 <1> ; EBX = virtual address 12235 <1> ; u.pgdir = page directory (physical) address 12236 <1> ; 12237 <1> ; OUTPUT -> 12238 <1> ; EAX = physical address 12239 <1> ; EBX = linear address 12240 <1> ; EDX = physical address of the page frame 12241 <1> ; (with attribute bits) 12242 <1> ; ECX = byte count within the page frame 12243 <1> ; 12244 <1> ; Modified Registers -> EAX, EBX, ECX, EDX 12245 <1> ; 12246 <1> 12247 <1> ; 19/04/2020 - Retro UNIX386 v2 12248 000027C7 A1[046D0000] <1> mov eax, [u.pgdir] 12249 <1> 12250 <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2 12251 <1> 12252 000027CC 81C300004000 <1> add ebx, CORE ; 18/10/2015 12253 <1> ; 12254 <1> ;mov eax, [u.pgdir] 12255 000027D2 E81AFDFFFF <1> call get_pte 12256 <1> ; EDX = Page table entry address (if CF=0) 12257 <1> ; Page directory entry address (if CF=1) 12258 <1> ; (Bit 0 value is 0 if PT is not present) 12259 <1> ; EAX = Page table entry value (page address) 12260 <1> ; CF = 1 -> PDE not present or invalid ? 12261 000027D7 731C <1> jnc short gpa_1 12262 <1> ; 12263 000027D9 E801FCFFFF <1> call allocate_page 12264 000027DE 724B <1> jc short gpa_im_err ; 'insufficient memory' error 12265 <1> gpa_0: 12266 000027E0 E86BFCFFFF <1> call clear_page 12267 <1> ; EAX = Physical (base) address of the allocated (new) page 12268 000027E5 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7 12269 <1> ; lower 3 bits are used as U/S, R/W, P flags 12270 <1> ; (user, writable, present page) 12271 000027E7 8902 <1> mov [edx], eax ; Let's put the new page directory entry here ! 12272 000027E9 A1[046D0000] <1> mov eax, [u.pgdir] 12273 000027EE E8FEFCFFFF <1> call get_pte 12274 000027F3 7236 <1> jc short gpa_im_err ; 'insufficient memory' error 12275 <1> gpa_1: 12276 <1> ; EAX = PTE value, EDX = PTE address 12277 000027F5 A801 <1> test al, PTE_A_PRESENT 12278 000027F7 750A <1> jnz short gpa_3 12279 000027F9 09C0 <1> or eax, eax 12280 000027FB 7420 <1> jz short gpa_4 ; Allocate a new page 12281 <1> 12282 <1> ; 17/04/2021 12283 <1> ; ('reload_page' procedure call is disabled as temporary) 12284 000027FD EB2C <1> jmp short gpa_im_err ; temporary ! 12285 <1> 12286 <1> ; 20/07/2015 12287 <1> ; push ebp 12288 <1> ; mov ebp, ebx ; virtual (linear) address 12289 <1> ; ; reload swapped page 12290 <1> ; call reload_page ; 28/04/2015 12291 <1> ; pop ebp 12292 <1> ; jc short gpa_retn 12293 <1> gpa_2: 12294 <1> ; 17/04/2021 12295 <1> ; ('add_to_swap_queue' procedure call is disabled as temporary) 12296 <1> 12297 <1> ; 20/07/2015 12298 <1> ; 20/05/2015 12299 <1> ; add this page to swap queue 12300 <1> ; push eax 12301 <1> ; ; EBX = Linear (CORE+virtual) address ; 20/02/2017 12302 <1> ; call add_to_swap_queue 12303 <1> ; pop eax 12304 <1> ; PTE address in EDX 12305 <1> ; virtual address in EBX 12306 <1> 12307 <1> ; EAX = memory page address 12308 000027FF 0C07 <1> or al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE 12309 <1> ; present flag, bit 0 = 1 12310 <1> ; user flag, bit 2 = 1 12311 <1> ; writable flag, bit 1 = 1 12312 00002801 8902 <1> mov [edx], eax ; Update PTE value 12313 <1> gpa_3: 12314 <1> ; 18/10/2015 12315 00002803 89D9 <1> mov ecx, ebx 12316 00002805 81E1FF0F0000 <1> and ecx, PAGE_OFF 12317 0000280B 89C2 <1> mov edx, eax 12318 0000280D 662500F0 <1> and ax, PTE_A_CLEAR 12319 00002811 01C8 <1> add eax, ecx 12320 00002813 F7D9 <1> neg ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095 12321 00002815 81C100100000 <1> add ecx, PAGE_SIZE 12322 0000281B F8 <1> clc 12323 <1> gpa_retn: 12324 0000281C C3 <1> retn 12325 <1> gpa_4: 12326 0000281D E8BDFBFFFF <1> call allocate_page 12327 00002822 7207 <1> jc short gpa_im_err ; 'insufficient memory' error 12328 00002824 E827FCFFFF <1> call clear_page 12329 00002829 EBD4 <1> jmp short gpa_2 12330 <1> 12331 <1> gpa_im_err: 12332 0000282B B804000000 <1> mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 12333 <1> ; Major error = 0 (No protection fault) 12334 00002830 C3 <1> retn 12335 <1> 12336 <1> ; 17/04/2021 12337 <1> ; ('reload_page' procedure call is disabled as temporary) 12338 <1> 12339 <1> ; 30/11/2021 - temporary ! 12340 <1> ;reload_page: 12341 <1> ; 20/07/2015 12342 <1> ; 28/04/2015 (Retro UNIX 386 v1 - beginning) 12343 <1> ; 12344 <1> ; Reload (Restore) swapped page at memory 12345 <1> ; 12346 <1> ; INPUT -> 12347 <1> ; EBP = Virtual (linear) memory address 12348 <1> ; EAX = PTE value (swap disk sector address) 12349 <1> ; (Swap disk sector address = bit 1 to bit 31 of EAX) 12350 <1> ; OUTPUT -> 12351 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE 12352 <1> ; 12353 <1> ; CF = 1 and EAX = error code 12354 <1> ; 12355 <1> ; Modified Registers -> none (except EAX) 12356 <1> ; 12357 <1> ; shr eax, 1 ; Convert PTE value to swap disk address 12358 <1> ; push ebx ; 12359 <1> ; mov ebx, eax ; Swap disk (offset) address 12360 <1> ; call allocate_page 12361 <1> ; jc short rlp_im_err 12362 <1> ; xchg eax, ebx 12363 <1> ; ; EBX = Physical memory (page) address 12364 <1> ; ; EAX = Swap disk (offset) address 12365 <1> ; ; EBP = Virtual (linear) memory address 12366 <1> ; call swap_in 12367 <1> ; jc short rlp_swp_err ; (swap disk/file read error) 12368 <1> ; mov eax, ebx 12369 <1> ;rlp_retn: 12370 <1> ; pop ebx 12371 <1> ; retn 12372 <1> ; 12373 <1> ;rlp_im_err: 12374 <1> ; mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 12375 <1> ; ; Major error = 0 (No protection fault) 12376 <1> ; jmp short rlp_retn 12377 <1> ; 12378 <1> ;rlp_swp_err: 12379 <1> ; mov eax, SWP_DISK_READ_ERR ; Swap disk read error ! 12380 <1> ; jmp short rlp_retn 12381 <1> 12382 <1> copy_page_dir: 12383 <1> ; 17/04/2021 (temporary modifications) 12384 <1> ; 19/09/2015 12385 <1> ; temporary - 07/09/2015 12386 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 12387 <1> ; 12388 <1> ; INPUT -> 12389 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 12390 <1> ; page directory. 12391 <1> ; OUTPUT -> 12392 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 12393 <1> ; page directory. 12394 <1> ; (New page directory with new page table entries.) 12395 <1> ; (New page tables with read only copies of the parent's 12396 <1> ; pages.) 12397 <1> ; EAX = 0 -> Error (CF = 1) 12398 <1> ; 12399 <1> ; Modified Registers -> none (except EAX) 12400 <1> ; 12401 00002831 E8A9FBFFFF <1> call allocate_page 12402 00002836 723E <1> jc short cpd_err 12403 <1> ; 12404 00002838 55 <1> push ebp ; 20/07/2015 12405 00002839 56 <1> push esi 12406 0000283A 57 <1> push edi 12407 0000283B 53 <1> push ebx 12408 0000283C 51 <1> push ecx 12409 0000283D 8B35[046D0000] <1> mov esi, [u.pgdir] 12410 00002843 89C7 <1> mov edi, eax 12411 00002845 50 <1> push eax ; save child's page directory address 12412 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 12413 <1> ; (use same system space for all user page tables) 12414 00002846 A5 <1> movsd 12415 00002847 BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 12416 0000284C B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 12417 <1> cpd_0: 12418 00002851 AD <1> lodsd 12419 <1> ;or eax, eax 12420 <1> ;jnz short cpd_1 12421 00002852 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 12422 00002854 7508 <1> jnz short cpd_1 12423 <1> ; (virtual address at the end of the page table) 12424 00002856 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 12425 0000285C EB0F <1> jmp short cpd_2 12426 <1> cpd_1: 12427 0000285E 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 12428 00002862 89C3 <1> mov ebx, eax 12429 <1> ; EBX = Parent's page table address 12430 00002864 E81F000000 <1> call copy_page_table 12431 00002869 720C <1> jc short cpd_p_err 12432 <1> ; EAX = Child's page table address 12433 0000286B 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 12434 <1> ; set bit 0, bit 1 and bit 2 to 1 12435 <1> ; (present, writable, user) 12436 <1> cpd_2: 12437 0000286D AB <1> stosd 12438 0000286E E2E1 <1> loop cpd_0 12439 <1> ; 12440 00002870 58 <1> pop eax ; restore child's page directory address 12441 <1> cpd_3: 12442 00002871 59 <1> pop ecx 12443 00002872 5B <1> pop ebx 12444 00002873 5F <1> pop edi 12445 00002874 5E <1> pop esi 12446 00002875 5D <1> pop ebp 12447 <1> cpd_err: 12448 00002876 C3 <1> retn 12449 <1> cpd_p_err: 12450 <1> ; release the allocated pages missing (recover free space) 12451 00002877 58 <1> pop eax ; the new page directory address (physical) 12452 00002878 8B1D[046D0000] <1> mov ebx, [u.pgdir] ; parent's page directory address 12453 0000287E E88CFCFFFF <1> call deallocate_page_dir 12454 00002883 29C0 <1> sub eax, eax ; 0 12455 00002885 F9 <1> stc 12456 00002886 EBE9 <1> jmp short cpd_3 12457 <1> 12458 <1> copy_page_table: 12459 <1> ; 17/04/2021 (temporary modifications) 12460 <1> ; 19/09/2015 12461 <1> ; temporary - 07/09/2015 12462 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 12463 <1> ; 12464 <1> ; INPUT -> 12465 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 12466 <1> ; EBP = page table entry index (from 'copy_page_dir') 12467 <1> ; OUTPUT -> 12468 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 12469 <1> ; EBP = (recent) page table index (for 'add_to_swap_queue') 12470 <1> ; CF = 1 -> error 12471 <1> ; 12472 <1> ; Modified Registers -> EBP (except EAX) 12473 <1> ; 12474 00002888 E852FBFFFF <1> call allocate_page 12475 0000288D 7244 <1> jc short cpt_err 12476 <1> ; 12477 0000288F 50 <1> push eax ; * 12478 <1> ;push ebx 12479 00002890 56 <1> push esi 12480 00002891 57 <1> push edi 12481 00002892 52 <1> push edx 12482 00002893 51 <1> push ecx 12483 <1> ; 12484 00002894 89DE <1> mov esi, ebx 12485 00002896 89C7 <1> mov edi, eax 12486 00002898 89C2 <1> mov edx, eax 12487 0000289A 81C200100000 <1> add edx, PAGE_SIZE 12488 <1> cpt_0: 12489 000028A0 AD <1> lodsd 12490 000028A1 A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 12491 <1> ;jnz short cpt_1 (*) 12492 <1> ; 17/04/2021 (temporary (*) 12493 <1> ;and eax, eax (*) 12494 000028A3 741E <1> jz short cpt_2 ; 17/04/2021 12495 <1> 12496 <1> ; 17/04/2021 12497 <1> ; ('reload_page' procedure call is disabled as temporary) 12498 <1> ; 12499 <1> ; ; ebp = virtual (linear) address of the memory page 12500 <1> ; call reload_page ; 28/04/2015 12501 <1> ; jc short cpt_p_err 12502 <1> cpt_1: 12503 000028A5 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 12504 000028A9 89C1 <1> mov ecx, eax 12505 <1> ; Allocate a new page for the child process 12506 000028AB E82FFBFFFF <1> call allocate_page 12507 000028B0 721C <1> jc short cpt_p_err 12508 000028B2 57 <1> push edi 12509 000028B3 56 <1> push esi 12510 000028B4 89CE <1> mov esi, ecx 12511 000028B6 89C7 <1> mov edi, eax 12512 000028B8 B900040000 <1> mov ecx, PAGE_SIZE/4 12513 000028BD F3A5 <1> rep movsd ; copy page (4096 bytes) 12514 000028BF 5E <1> pop esi 12515 000028C0 5F <1> pop edi 12516 <1> ; 12517 <1> ; 17/04/2021 12518 <1> ; ('add_to_swap_queue' procedure call is disabled as temporary) 12519 <1> ; 12520 <1> ; push ebx 12521 <1> ; push eax 12522 <1> ; mov ebx, ebp 12523 <1> ; ; ebx = virtual address of the memory page 12524 <1> ; call add_to_swap_queue 12525 <1> ; pop eax 12526 <1> ; pop ebx 12527 <1> ; 12528 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 12529 000028C1 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 12530 <1> cpt_2: 12531 000028C3 AB <1> stosd ; EDI points to child's PTE 12532 <1> ; 12533 000028C4 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 12534 <1> ; 12535 000028CA 39D7 <1> cmp edi, edx 12536 000028CC 72D2 <1> jb short cpt_0 12537 <1> cpt_p_err: 12538 000028CE 59 <1> pop ecx 12539 000028CF 5A <1> pop edx 12540 000028D0 5F <1> pop edi 12541 000028D1 5E <1> pop esi 12542 <1> ;pop ebx 12543 000028D2 58 <1> pop eax ; * 12544 <1> cpt_err: 12545 000028D3 C3 <1> retn 12546 <1> 12547 <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS /// 12548 <1> 12549 <1> ;; Data: 12550 <1> 12551 <1> ; 09/03/2015 12552 <1> ;swpq_count: dw 0 ; count of pages on the swap que 12553 <1> ;swp_drv: dd 0 ; logical drive description table address of the swap drive/disk 12554 <1> ;swpd_size: dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 12555 <1> ;swpd_free: dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical) 12556 <1> ;swpd_next: dd 0 ; next free page block 12557 <1> ;swpd_last: dd 0 ; last swap page block 12558 %include 'sysdefs.s' ; 09/03/2015 12559 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 12560 <1> ; (re-write kernel for test by using previous version without a major defect) 12561 <1> ; **************************************************************************** 12562 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.4) - SYSDEFS.INC 12563 <1> ; Last Modification: 27/12/2022 12564 <1> ; 12565 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 12566 <1> ; (Modified from 12567 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 12568 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 12569 <1> ; UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11) 12570 <1> ; ---------------------------------------------------------------------------- 12571 <1> ; 12572 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 12573 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 12574 <1> ; 12575 <1> ; 12576 <1> ; 12577 <1> ; **************************************************************************** 12578 <1> 12579 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 12580 <1> ; (SB structure has been moved here from 'ux.s' 12581 <1> ; to overcome NASM's bss addressing bug !!!) 12582 <1> ; (('ux.s' bss section addresses are being overlapped 12583 <1> ; when SB structure is defined in 'ux.s')) 12584 <1> 12585 <1> struc SB ; SuperBlock 12586 <1> 12587 00000000 <1> .Header: resd 1 12588 <1> ;.HiddenSects: 12589 00000004 <1> .BootSectAddr: resd 1 ; Hidden Sectors 12590 <1> ;.TotalSects: 12591 00000008 <1> .VolumeSize: resd 1 ; Entire Volume/Partition Size (includes ext. volume) 12592 0000000C <1> .Version: resd 1 12593 00000010 <1> .BlockSize: resd 1 12594 00000014 <1> .InodeCount: resd 1 12595 00000018 <1> .FreeMapAddr: resd 1 12596 0000001C <1> .FreeMapSize: resd 1 12597 00000020 <1> .InodeMapAddr: resd 1 12598 00000024 <1> .InodeMapSize: resd 1 12599 00000028 <1> .InodeTblAddr: resd 1 12600 0000002C <1> .InodeTblSize: resd 1 12601 00000030 <1> .FreeInodes: resd 1 12602 00000034 <1> .FirstFreeIno: resd 1 12603 00000038 <1> .FreeBlocks: resd 1 12604 0000003C <1> .FirstFreeBlk: resd 1 12605 00000040 <1> .BootSecParms: resb 19 ; v1 12606 00000053 <1> .BSExtension: resb 5 ; v2 HDFS 12607 00000058 <1> .Status: resb 1 ; 12/05/2021 (system modification status) (*) 12608 00000059 <1> .Pdrv: resb 1 ; Physical disk number (index) ; 12/05/2021 (*) 12609 0000005A <1> .Uno: resw 1 ; user/process number ; 12/05/2021 (*) 12610 0000005C <1> .ModifTime: resd 1 ; (last) modification time (*) 12611 00000060 <1> .ExtdVolTbl: resd 1 ; Extended Volume Start/Table Address 12612 00000064 <1> .ExtdVolSize: resd 1 ; Extended Volume (swap section etc.) Size 12613 00000068 <1> .LBA_rw: resb 1 12614 00000069 <1> .ClusterSize: resb 1 12615 0000006A <1> .ReadOnly: resb 1 ; (SB will not be written to disk if bit 0 is 1) 12616 0000006B <1> .Mounted: resb 1 12617 0000006C <1> .MountInode: resd 1 ; double word 12618 00000070 <1> .DevMajor: resb 1 12619 00000071 <1> .DevMinor: resb 1 12620 00000072 <1> .LongName: resb 1 12621 00000073 <1> .Direntry32: resb 1 12622 <1> ; 18/07/2021 12623 00000074 <1> .FileBuffer: resd 1 12624 00000078 <1> .ItabBuffer: resd 1 12625 0000007C <1> .ImapBuffer: resd 1 12626 00000080 <1> .FmapBuffer: resd 1 12627 <1> ; 15/07/2021 12628 00000084 <1> .LastInode: resd 1 12629 <1> ; 02/05/2021 12630 00000088 <1> .FmapIndex: resd 1 12631 0000008C <1> .ImapIndex: resd 1 12632 00000090 <1> .ItableIndex: resd 1 12633 00000094 <1> .Reserved: resb 508-148 ; 18/07/2021 12634 000001FC <1> .Footer: resd 1 12635 <1> 12636 <1> endstruc 12637 <1> 12638 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 12639 <1> ; (file structure has been moved here from 'ux.s' 12640 <1> ; to overcome NASM's bss addressing bug !!!) 12641 <1> ; (('ux.s' bss section addresses are being overlapped 12642 <1> ; when file structure is defined in 'ux.s')) 12643 <1> 12644 <1> ; 22/11/2021 12645 <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision 12646 <1> 12647 <1> struc file ; open files (fsp) structure 12648 00000000 <1> .inode: resw 1 ; inode number of open file (32 bit) 12649 00000002 <1> .i32: resw 1 ; higher word of inode number (reserved) 12650 00000004 <1> .drive: resb 1 ; logical drive (disk) number 12651 00000005 <1> .flags: resb 1 ; open mode and status 12652 00000006 <1> .count: resb 1 ; number of processes that have file open 12653 <1> ;.rsvd: resb 1 ; reserved byte (for next versions) 12654 00000007 <1> .mnt: resb 1 ; mnttab index+1 (0 = not mounted) 12655 00000008 <1> .offset: resd 1 ; file offset/pointer (64 bit) 12656 0000000C <1> .o64: resd 1 ; higher 32 bit of file offset 12657 <1> .size: ; = 16 12658 <1> endstruc 12659 <1> 12660 <1> nproc equ 16 ; number of processes 12661 <1> ntty equ 8 ; 8+1 -> 8 (10/05/2013) 12662 <1> ;nbuf equ 6 ; number of buffers (04/02/2016) 12663 <1> nbuf equ 16 ; number of buffers ; 11/06/2022 12664 <1> nfiles equ 50 ; NFILES equ 50 ; 02/01/2022 12665 <1> 12666 <1> ; 27/12/2021 12667 <1> ;NFILES equ 32 ; temporary ! ( 27/12/2021) 12668 <1> ; 02/01/2022 12669 <1> ;OPENFILES equ 10 ; open files (for user) ; 28/03/2020 12670 <1> 12671 <1> ;csgmnt equ 2000h ; 26/05/2013 (segment of process 1) 12672 <1> ;core equ 0 ; 19/04/2013 12673 <1> ;ecore equ 32768 - 64 ; 04/06/2013 (24/05/2013) 12674 <1> ; (if total size of argument list and arguments is 128 bytes) 12675 <1> ; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes 12676 <1> ; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570) 12677 <1> ; initial value of user's stack pointer = 32768-64-128-2 = 32574 12678 <1> ; (sp=32768-args_space-2 at the beginning of execution) 12679 <1> ; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes) 12680 <1> ; 'u' structure offset (for the '/core' dump file) = 32704 12681 <1> ; '/core' dump file size = 32768 bytes 12682 <1> 12683 <1> ; 08/03/2014 12684 <1> ;sdsegmnt equ 6C0h ; 256*16 bytes (swap data segment size for 16 processes) 12685 <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only ! 12686 <1> ;;sdsegmnt equ 740h ; swap data segment (for user structures and registers) 12687 <1> 12688 <1> ; 30/08/2013 12689 <1> time_count equ 4 ; 10 --> 4 01/02/2014 12690 <1> 12691 <1> ; 05/02/2014 12692 <1> ; process status 12693 <1> ;SFREE equ 0 12694 <1> ;SRUN equ 1 12695 <1> ;SWAIT equ 2 12696 <1> ;SZOMB equ 3 12697 <1> ;SSLEEP equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup) 12698 <1> 12699 <1> ; 09/03/2015 12700 <1> userdata equ 80000h ; user structure data address for current user ; temporary 12701 <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary 12702 <1> swap_alloc_table equ 0D0000h ; swap allocation table address ; temporary 12703 <1> 12704 <1> ; 17/09/2015 12705 <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return 12706 <1> 12707 <1> ; 27/12/2022 (40) 12708 <1> ; 12/01/2022 (37,38,39) 12709 <1> ; 21/09/2015 (36) 12710 <1> ; 01/07/2015 (35) 12711 <1> ; 14/07/2013 (0-34) 12712 <1> ; UNIX v1 system calls 12713 <1> _rele equ 0 12714 <1> _exit equ 1 12715 <1> _fork equ 2 12716 <1> _read equ 3 12717 <1> _write equ 4 12718 <1> _open equ 5 12719 <1> _close equ 6 12720 <1> _wait equ 7 12721 <1> _creat equ 8 12722 <1> _link equ 9 12723 <1> _unlink equ 10 12724 <1> _exec equ 11 12725 <1> _chdir equ 12 12726 <1> _time equ 13 12727 <1> _mkdir equ 14 12728 <1> _chmod equ 15 12729 <1> _chown equ 16 12730 <1> _break equ 17 12731 <1> _stat equ 18 12732 <1> _seek equ 19 12733 <1> _tell equ 20 12734 <1> _mount equ 21 12735 <1> _umount equ 22 12736 <1> _setuid equ 23 12737 <1> _getuid equ 24 12738 <1> _stime equ 25 12739 <1> _quit equ 26 12740 <1> _intr equ 27 12741 <1> _fstat equ 28 12742 <1> _emt equ 29 12743 <1> _mdate equ 30 12744 <1> _stty equ 31 12745 <1> _gtty equ 32 12746 <1> _ilgins equ 33 12747 <1> _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 12748 <1> _msg equ 35 ; Retro UNIX 386 v1 feature only ! 12749 <1> _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 12750 <1> ; 12/01/2022 - Retro UNIX 386 v1.2 12751 <1> ; Retro UNIX 386 v2 system calls 12752 <1> _setgid equ 37 12753 <1> _getgid equ 38 12754 <1> _ver equ 39 ; (get) Retro Unix 386 version 12755 <1> ; 27/12/2022 - Retro UNIX 386 v1.2 12756 <1> _mem equ 40 ; get available memory 12757 <1> 12758 <1> %macro sys 1-4 12759 <1> ; 03/09/2015 12760 <1> ; 13/04/2015 12761 <1> ; Retro UNIX 386 v1 system call. 12762 <1> %if %0 >= 2 12763 <1> mov ebx, %2 12764 <1> %if %0 >= 3 12765 <1> mov ecx, %3 12766 <1> %if %0 = 4 12767 <1> mov edx, %4 12768 <1> %endif 12769 <1> %endif 12770 <1> %endif 12771 <1> mov eax, %1 12772 <1> int 30h 12773 <1> %endmacro 12774 <1> 12775 <1> ; 13/05/2015 - ERROR CODES 12776 <1> ERR_FILE_NOT_OPEN equ 10 ; 'file not open !' error 12777 <1> ERR_FILE_ACCESS equ 11 ; 'permission denied !' error 12778 <1> ; 14/05/2015 12779 <1> ERR_DIR_ACCESS equ 11 ; 'permission denied !' error 12780 <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error 12781 <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error 12782 <1> ERR_DIR_EXISTS equ 14 ; 'directory already exists !' error 12783 <1> ; 16/05/2015 12784 <1> ERR_DRV_NOT_RDY equ 15 ; 'drive not ready !' error 12785 <1> ; 18/05/2015 12786 <1> ERR_DEV_NOT_RDY equ 15 ; 'device not ready !' error 12787 <1> ERR_DEV_ACCESS equ 11 ; 'permission denied !' error 12788 <1> ERR_DEV_NOT_OPEN equ 10 ; 'device not open !' error 12789 <1> ; 07/06/2015 12790 <1> ERR_FILE_EOF equ 16 ; 'end of file !' error 12791 <1> ERR_DEV_VOL_SIZE equ 16 ; 'out of volume' error 12792 <1> ; 09/06/2015 12793 <1> ERR_DRV_READ equ 17 ; 'disk read error !' 12794 <1> ERR_DRV_WRITE equ 18 ; 'disk write error !' 12795 <1> ; 16/06/2015 12796 <1> ERR_NOT_DIR equ 19 ; 'not a (valid) directory !' error 12797 <1> ERR_FILE_SIZE equ 20 ; 'file size error !' 12798 <1> ; 22/06/2015 12799 <1> ERR_NOT_SUPERUSER equ 11 ; 'permission denied !' error 12800 <1> ERR_NOT_OWNER equ 11 ; 'permission denied !' error 12801 <1> ERR_NOT_FILE equ 11 ; 'permission denied !' error 12802 <1> ; 23/06/2015 12803 <1> ERR_FILE_EXISTS equ 14 ; 'file already exists !' error 12804 <1> ERR_DRV_NOT_SAME equ 21 ; 'not same drive !' error 12805 <1> ERR_DIR_NOT_FOUND equ 12 ; 'directory not found !' error 12806 <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error 12807 <1> ; 27/06/2015 12808 <1> ERR_INV_PARAMETER equ 23 ; 'invalid parameter !' error 12809 <1> ERR_INV_DEV_NAME equ 24 ; 'invalid device name !' error 12810 <1> ; 29/06/2015 12811 <1> ERR_TIME_OUT equ 25 ; 'time out !' error 12812 <1> ERR_DEV_NOT_RESP equ 25 ; 'device not responding !' error 12813 <1> ; 08/02/2022 12814 <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s') 12815 <1> ; 10/10/2016 12816 <1> ERR_INV_FILE_NAME equ 26 ; 'invalid file name !' error 12817 <1> ; 18/05/2016 12818 <1> ERR_MISC equ 27 ; miscellaneous/other errors 12819 <1> ; 15/10/2016 12820 <1> ERR_INV_FORMAT equ 28 ; 'invalid format !' error 12821 <1> ERR_INV_DATA equ 29 ; 'invalid data !' error 12822 <1> ; 16/10/2016 12823 <1> ERR_DISK_WRITE equ 30 ; 'disk write protected !' 12824 <1> ; 08/02/2022 12825 <1> ERR_INV_FS equ 28 ;'invalid fs/superblock !' error 12826 <1> 12827 <1> ; 12/06/2022 12828 <1> ; printer errors 12829 <1> ERR_PRN_NOT_RDY equ 15 ; 'device not ready !' error 12830 <1> ERR_PRN_TIMEOUT equ 25 ; 'time out !' error 12831 <1> ERR_PRN_PAPER equ 31 ; 'out of paper !' error 12832 <1> ERR_PRN_IO equ 32 ; 'io error !' error 12833 <1> ERR_PRN_BUSY equ 34 ; 'busy !' error 12834 <1> 12835 <1> ; 26/08/2015 12836 <1> ; 24/07/2015 12837 <1> ; 24/06/2015 12838 <1> MAX_ARG_LEN equ 256 ; max. length of sys exec arguments 12839 <1> ; 01/07/2015 12840 <1> MAX_MSG_LEN equ 255 ; max. msg length for 'sysmsg' 12841 <1> ; 12842 <1> ; 26/11/2021 ('no free blocks on disk !' error) 12843 <1> ERR_ALLOC equ 33 ; 'disk allocation error !' 12844 <1> ; 22/11/2021 12845 <1> ERR_READ_ONLY_FS equ 30 ; 'read only file system !' error 12846 <1> ; 28/11/2021 12847 <1> ERR_INV_FILE equ 255 ; 'invalid file (inode) !' error 12848 <1> ; 04/12/2021 12849 <1> ERR_PERM_DENIED equ 11 ; 'permission denied !' error 12850 <1> ; 11/12/2021 12851 <1> ERR_INV_FUNC equ 1 ; 'invalid system call !' error 12852 <1> ; 10/01/2022 12853 <1> ERR_INO_ALLOC equ 33 ; 'inode allocation error !' 12854 <1> ERR_NOT_REGULAR equ 255 ; 'not regular file directory !' error 12855 <1> 12856 <1> ; 12/01/2022 - Retro UNIX 386 v1.2 12857 <1> %define s.time systm+504 ; boot/sysinit time (or current time) 12858 <1> 12859 %include 'u0.s' ; 15/03/2015 12860 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 12861 <1> ; (re-write kernel for test by using previous version without a major defect) 12862 <1> ; **************************************************************************** 12863 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.3) - SYS0.INC 12864 <1> ; Last Modification: 17/07/2022 12865 <1> ; ---------------------------------------------------------------------------- 12866 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 12867 <1> ; (v0.1 - Beginning: 11/07/2012) 12868 <1> ; 12869 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 12870 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 12871 <1> ; 12872 <1> ; 12873 <1> ; 12874 <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s 12875 <1> ; 12876 <1> ; **************************************************************************** 12877 <1> 12878 <1> sys_init: 12879 <1> ; 23/02/2022 12880 <1> ; 08/01/2022 12881 <1> ; 01/01/2022 12882 <1> ; 26/12/2021 12883 <1> ; 27/11/2021 12884 <1> ; 22/11/2021 - Retro UNIX 386 v2 (test) compatibility modification 12885 <1> ; 18/10/2015 12886 <1> ; 28/08/2015 12887 <1> ; 24/08/2015 12888 <1> ; 14/08/2015 12889 <1> ; 24/07/2015 12890 <1> ; 02/07/2015 12891 <1> ; 01/07/2015 12892 <1> ; 23/06/2015 12893 <1> ; 15/04/2015 12894 <1> ; 13/04/2015 12895 <1> ; 11/03/2015 (Retro UNIX 386 v1 - Beginning) 12896 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 12897 <1> ; 12898 <1> ;call ldrv_init ; Logical drive description tables initialization 12899 <1> ; 12900 <1> ;; 14/02/2014 12901 <1> ;; 14/07/2013 12902 <1> ;mov ax, 41 12903 <1> ;mov [rootdir], ax 12904 <1> ;mov [u.cdir], ax 12905 <1> ;and al, 1 ; 15/04/2015 12906 <1> 12907 <1> ; 27/11/2021 12908 <1> ; 18/04/2021 - Retro UNIX 386 v2 12909 000028D4 31C0 <1> xor eax, eax 12910 000028D6 FEC0 <1> inc al ; eax = 1 (root directory inode) ; runix v2 fs 12911 000028D8 A3[866C0000] <1> mov [rootdir], eax ; = 1 ; 28/10/2021 (32 bit) 12912 000028DD A3[A86C0000] <1> mov [u.cdir], eax ; 28/10/2021 (32 bit) 12913 <1> 12914 000028E2 A2[F56C0000] <1> mov [u.uno], al ; = 1 12915 <1> ;mov [mpid], ax ; 1 12916 <1> ;mov [p.pid], ax ; 1 12917 <1> ; 01/01/2022 12918 000028E7 A2[846C0000] <1> mov [mpid], al 12919 000028EC A2[64680000] <1> mov [p.pid], al 12920 000028F1 A2[C4680000] <1> mov [p.stat], al ; SRUN, 05/02/2014 12921 <1> ; 12922 000028F6 B004 <1> mov al, time_count ; 30/08/2013 12923 000028F8 A2[EC6C0000] <1> mov [u.quant], al ; 14/07/2013 12924 <1> ; 02/07/2015 12925 000028FD A1[68670000] <1> mov eax, [k_page_dir] 12926 00002902 A3[046D0000] <1> mov [u.pgdir], eax ; reset 12927 <1> ; 18/10/2015 12928 <1> ;sub eax, eax 12929 <1> ;mov [u.ppgdir], eax ; 0 12930 <1> ; 12931 <1> ; 23/02/2022 12932 <1> ;call epoch 12933 <1> ;mov [s.time], eax ; 13/03/2015 12934 <1> ; 17/07/2013 12935 00002907 E881060000 <1> call bf_init ; buffer initialization 12936 <1> ; 23/02/2022 12937 <1> ; (save sysinit time on sb0) 12938 0000290C E829030000 <1> call epoch 12939 00002911 A3[4C6F0000] <1> mov [s.time], eax ; 13/03/2015 12940 <1> ; 23/06/2015 12941 00002916 E8C4FAFFFF <1> call allocate_page 12942 <1> ;;jc error 12943 <1> ;jc panic ; jc short panic (01/07/2015) 12944 <1> ; 05/12/2021 12945 0000291B 7305 <1> jnc short sysinit_1 12946 0000291D E989000000 <1> jmp panic 12947 <1> sysinit_1: 12948 00002922 A3[006D0000] <1> mov [u.upage], eax ; user structure page 12949 00002927 A3[D4680000] <1> mov [p.upage], eax 12950 <1> ; 12951 0000292C E81FFBFFFF <1> call clear_page 12952 <1> ; 12953 <1> ; 14/08/2015 12954 00002931 FA <1> cli 12955 <1> ; 14/03/2015 12956 <1> ; 17/01/2014 12957 00002932 E8D0010000 <1> call sp_init ; serial port initialization 12958 <1> ; 14/08/2015 12959 00002937 FB <1> sti 12960 <1> ; 12961 <1> ; 30/06/2015 12962 <1> ;mov esi, kernel_init_ok_msg 12963 <1> ;call print_msg 12964 <1> ; 12965 00002938 30DB <1> xor bl, bl ; video page 0 12966 <1> vp_clr_nxt: ; clear video pages (reset cursor positions) 12967 0000293A E8D2330000 <1> call vp_clr ; 17/07/2013 12968 0000293F FEC3 <1> inc bl 12969 00002941 80FB08 <1> cmp bl, 8 12970 00002944 72F4 <1> jb short vp_clr_nxt 12971 <1> ; 12972 <1> ; 24/07/2015 12973 <1> ;push KDATA 12974 <1> ;push esp 12975 <1> ;mov [tss.esp0], esp 12976 <1> ;mov word [tss.ss0], KDATA 12977 <1> ; 12978 <1> ; 08/01/2022 12979 <1> ; 24/08/2015 12980 <1> ;; temporary (01/07/2015) 12981 <1> ;mov byte [u.quant], time_count ; 4 12982 <1> ; ; it is not needed here ! 12983 <1> ;;inc byte [u.kcall] ; 'the caller is kernel' sign 12984 00002946 FE0D[986C0000] <1> dec byte [sysflg] ; FFh = ready for system call 12985 <1> ; 0 = executing a system call 12986 <1> ;;sys _msg, kernel_init_ok_msg, 255, 0 12987 <1> ; 12988 <1> ;;; 06/08/2015 12989 <1> ;;;call getch ; wait for a key stroke 12990 <1> ;;mov ecx, 0FFFFFFFh 12991 <1> ;;sys_init_msg_wait: 12992 <1> ;; push ecx 12993 <1> ;; mov al, 1 12994 <1> ;; mov ah, [ptty] ; active (current) video page 12995 <1> ;; call getc_n 12996 <1> ;; pop ecx 12997 <1> ;; jnz short sys_init_msg_ok 12998 <1> ;; loop sys_init_msg_wait 12999 <1> ; 13000 <1> ;;sys_init_msg_ok: 13001 <1> ; 28/08/2015 (initial settings for the 1st 'rswap') 13002 0000294C 6A10 <1> push KDATA ; ss 13003 0000294E 54 <1> push esp 13004 0000294F 9C <1> pushfd 13005 00002950 6A08 <1> push KCODE ; cs 13006 00002952 68[7F290000] <1> push init_exec ; eip 13007 00002957 8925[9C6C0000] <1> mov [u.sp], esp 13008 0000295D 1E <1> push ds 13009 0000295E 06 <1> push es 13010 0000295F 0FA0 <1> push fs 13011 00002961 0FA8 <1> push gs 13012 00002963 60 <1> pushad 13013 00002964 8925[A06C0000] <1> mov [u.usp], esp 13014 0000296A E8091D0000 <1> call wswap ; save current user (u) structure, user registers 13015 <1> ; and interrupt return components (for IRET) 13016 0000296F 61 <1> popad 13017 00002970 6658 <1> pop ax ; gs 13018 00002972 6658 <1> pop ax ; fs 13019 00002974 6658 <1> pop ax ; es 13020 00002976 6658 <1> pop ax ; ds 13021 00002978 58 <1> pop eax ; eip (init_exec) 13022 00002979 6658 <1> pop ax ; cs (KCODE) 13023 0000297B 58 <1> pop eax ; E-FLAGS 13024 0000297C 58 <1> pop eax ; esp 13025 0000297D 6658 <1> pop ax ; ss (KDATA) 13026 <1> ; 13027 <1> ; 26/12/2021 ([u.ppgdir] is zero already) 13028 <1> ;xor eax, eax ; 0 13029 <1> ;mov [u.ppgdir], eax ; reset (to zero) for '/etc/init' 13030 <1> ; 13031 <1> ; 02/07/2015 13032 <1> ; [u.pgdir ] = [k_page_dir] 13033 <1> ; [u.ppgdir] = 0 (page dir of the parent process) 13034 <1> ; (The caller is os kernel sign for 'sysexec') 13035 <1> init_exec: 13036 <1> ; 13/03/2013 13037 <1> ; 24/07/2013 13038 0000297F BB[A1290000] <1> mov ebx, init_file 13039 00002984 B9[99290000] <1> mov ecx, init_argp 13040 <1> ; EBX contains 'etc/init' asciiz file name address 13041 <1> ; ECX contains address of argument list pointer 13042 <1> ; 13043 <1> ;dec byte [sysflg] ; FFh = ready for system call 13044 <1> ; 0 = executing a system call 13045 <1> sys _exec ; execute file 13046 <2> 13047 <2> 13048 <2> 13049 <2> %if %0 >= 2 13050 <2> mov ebx, %2 13051 <2> %if %0 >= 3 13052 <2> mov ecx, %3 13053 <2> %if %0 = 4 13054 <2> mov edx, %4 13055 <2> %endif 13056 <2> %endif 13057 <2> %endif 13058 00002989 B80B000000 <2> mov eax, %1 13059 0000298E CD30 <2> int 30h 13060 00002990 7319 <1> jnc short panic 13061 <1> ; 13062 00002992 BE[80640000] <1> mov esi, etc_init_err_msg 13063 <1> ; 22/11/2021 13064 <1> ;call print_msg 13065 00002997 EB17 <1> jmp short key_to_reboot 13066 <1> 13067 <1> ;align 4 13068 <1> init_argp: 13069 00002999 [A1290000]00000000 <1> dd init_file, 0 ; 23/06/2015 (dw -> dd) 13070 <1> init_file: 13071 <1> ; 24/08/2015 13072 000029A1 2F6574632F696E6974- <1> db '/etc/init', 0 13073 000029AA 00 <1> 13074 <1> panic: 13075 <1> ; 13/03/2015 (Retro UNIX 386 v1) 13076 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 13077 000029AB BE[65640000] <1> mov esi, panic_msg 13078 <1> key_to_reboot: ; 22/11/2021 13079 000029B0 E819000000 <1> call print_msg 13080 <1> ;key_to_reboot: 13081 <1> ; 15/11/2015 13082 000029B5 E8A5310000 <1> call getch 13083 <1> ; wait for a character from the current tty 13084 <1> ; 13085 000029BA B00A <1> mov al, 0Ah 13086 000029BC 8A1D[96670000] <1> mov bl, [ptty] ; [active_page] 13087 000029C2 B407 <1> mov ah, 07h ; Black background, 13088 <1> ; light gray forecolor 13089 000029C4 E8EBE8FFFF <1> call write_tty 13090 000029C9 E98AE5FFFF <1> jmp cpu_reset 13091 <1> 13092 <1> print_msg: 13093 <1> ; 01/07/2015 13094 <1> ; 13/03/2015 (Retro UNIX 386 v1) 13095 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 13096 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 13097 <1> ; 13098 <1> ; 13099 000029CE AC <1> lodsb 13100 <1> pmsg1: 13101 000029CF 56 <1> push esi 13102 000029D0 0FB61D[96670000] <1> movzx ebx, byte [ptty] 13103 000029D7 B407 <1> mov ah, 07h ; Black background, light gray forecolor 13104 000029D9 E8D6E8FFFF <1> call write_tty 13105 000029DE 5E <1> pop esi 13106 000029DF AC <1> lodsb 13107 000029E0 20C0 <1> and al, al 13108 000029E2 75EB <1> jnz short pmsg1 13109 000029E4 C3 <1> retn 13110 <1> 13111 <1> ctrlbrk: 13112 <1> ; 06/02/2022 13113 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 13114 <1> ; 12/11/2015 13115 <1> ; 13/03/2015 (Retro UNIX 386 v1) 13116 <1> ; 06/12/2013 (Retro UNIX 8086 v1) 13117 <1> ; 13118 <1> ; INT 1Bh (control+break) handler 13119 <1> ; 13120 <1> ; Retro Unix 8086 v1 feature only! 13121 <1> ; 13122 000029E5 66833D[F06C0000]00 <1> cmp word [u.intr], 0 13123 000029ED 764B <1> jna short cbrk4 13124 <1> cbrk0: 13125 <1> ; 12/11/2015 13126 <1> ; 06/12/2013 13127 000029EF 66833D[F26C0000]00 <1> cmp word [u.quit], 0 13128 000029F7 7441 <1> jz short cbrk4 13129 <1> ; 13130 <1> ; 20/09/2013 13131 <1> ;push ax 13132 <1> ; 04/12/2021 13133 000029F9 50 <1> push eax 13134 <1> 13135 <1> ; 06/02/2022 13136 <1> ; (repetitive ctrl+brk check) 13137 000029FA 66A1[F26C0000] <1> mov ax, [u.quit] 13138 00002A00 6640 <1> inc ax ; 0FFFFh -> 0 13139 00002A02 7435 <1> jz short cbrk3 13140 <1> 13141 <1> ; 06/12/2013 13142 00002A04 A0[96670000] <1> mov al, [ptty] 13143 <1> ; 13144 <1> ; 12/11/2015 13145 <1> ; 13146 <1> ; ctrl+break (EOT, CTRL+D) from serial port 13147 <1> ; or ctrl+break from console (pseudo) tty 13148 <1> ; (!redirection!) 13149 <1> ; 13150 00002A09 3C08 <1> cmp al, 8 ; serial port tty nums > 7 13151 00002A0B 7211 <1> jb short cbrk1 ; console (pseudo) tty 13152 <1> ; 13153 <1> ; Serial port interrupt handler sets [ptty] 13154 <1> ; to the port's tty number (as temporary). 13155 <1> ; 13156 <1> ; If active process is using a stdin or 13157 <1> ; stdout redirection (by the shell), 13158 <1> ; console tty keyboard must be available 13159 <1> ; to terminate running process, 13160 <1> ; in order to prevent a deadlock. 13161 <1> ; 13162 00002A0D 52 <1> push edx 13163 00002A0E 0FB615[F56C0000] <1> movzx edx, byte [u.uno] 13164 00002A15 3A82[A3680000] <1> cmp al, [edx+p.ttyc-1] ; console tty (rw) 13165 00002A1B 5A <1> pop edx 13166 00002A1C 7412 <1> je short cbrk2 13167 <1> cbrk1: 13168 00002A1E FEC0 <1> inc al ; [u.ttyp] : 1 based tty number 13169 <1> ; 06/12/2013 13170 00002A20 3A05[DA6C0000] <1> cmp al, [u.ttyp] ; recent open tty (r) 13171 00002A26 7408 <1> je short cbrk2 13172 00002A28 3A05[DB6C0000] <1> cmp al, [u.ttyp+1] ; recent open tty (w) 13173 00002A2E 7509 <1> jne short cbrk3 13174 <1> cbrk2: 13175 <1> ;; 06/12/2013 13176 <1> ;mov ax, [u.quit] 13177 <1> ;and ax, ax 13178 <1> ;jz short cbrk3 13179 <1> ; 13180 <1> ;xor ax, ax ; 0 13181 <1> ;dec ax 13182 <1> ; 04/12/2021 13183 00002A30 31C0 <1> xor eax, eax ; 0 13184 00002A32 48 <1> dec eax ; 0FFFFFFFFh 13185 <1> ; 0FFFFh = 'ctrl+brk' keystroke 13186 00002A33 66A3[F26C0000] <1> mov [u.quit], ax 13187 <1> cbrk3: 13188 <1> ;pop ax 13189 <1> ; 04/12/2021 13190 00002A39 58 <1> pop eax 13191 <1> cbrk4: 13192 00002A3A C3 <1> retn 13193 <1> 13194 <1> com2_int: 13195 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 13196 <1> ; 07/11/2015 13197 <1> ; 24/10/2015 13198 <1> ; 23/10/2015 13199 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 13200 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 13201 <1> ; < serial port 2 interrupt handler > 13202 <1> ; 13203 00002A3B 890424 <1> mov [esp], eax ; overwrite call return address 13204 <1> ;;push eax 13205 <1> ; 08/01/2022 13206 00002A3E 29C0 <1> sub eax, eax 13207 00002A40 B009 <1> mov al, 9 13208 <1> ;mov ax, 9 13209 00002A42 EB07 <1> jmp short comm_int 13210 <1> com1_int: 13211 <1> ; 07/11/2015 13212 <1> ; 24/10/2015 13213 00002A44 890424 <1> mov [esp], eax ; overwrite call return address 13214 <1> ; 23/10/2015 13215 <1> ;push eax 13216 <1> ; 08/01/2022 13217 00002A47 29C0 <1> sub eax, eax 13218 00002A49 B008 <1> mov al, 8 13219 <1> ;mov ax, 8 13220 <1> comm_int: 13221 <1> ; 08/01/2022 13222 <1> ; 20/11/2015 13223 <1> ; 18/11/2015 13224 <1> ; 17/11/2015 13225 <1> ; 16/11/2015 13226 <1> ; 09/11/2015 13227 <1> ; 08/11/2015 13228 <1> ; 07/11/2015 13229 <1> ; 06/11/2015 (serial4.asm, 'serial') 13230 <1> ; 01/11/2015 13231 <1> ; 26/10/2015 13232 <1> ; 23/10/2015 13233 00002A4B 53 <1> push ebx 13234 00002A4C 56 <1> push esi 13235 00002A4D 57 <1> push edi 13236 00002A4E 1E <1> push ds 13237 00002A4F 06 <1> push es 13238 <1> ; 18/11/2015 13239 00002A50 0F20DB <1> mov ebx, cr3 13240 00002A53 53 <1> push ebx ; **** 13241 <1> ; 13242 00002A54 51 <1> push ecx ; *** 13243 00002A55 52 <1> push edx ; ** 13244 <1> ; 13245 00002A56 BB10000000 <1> mov ebx, KDATA 13246 00002A5B 8EDB <1> mov ds, bx 13247 00002A5D 8EC3 <1> mov es, bx 13248 <1> ; 13249 00002A5F 8B0D[68670000] <1> mov ecx, [k_page_dir] 13250 00002A65 0F22D9 <1> mov cr3, ecx 13251 <1> ; 20/11/2015 13252 <1> ; Interrupt identification register 13253 00002A68 66BAFA02 <1> mov dx, 2FAh ; COM2 13254 <1> ; 13255 00002A6C 3C08 <1> cmp al, 8 13256 00002A6E 7702 <1> ja short com_i0 13257 <1> ; 13258 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 13259 <1> ; 20/11/2015 13260 <1> ; 17/11/2015 13261 <1> ; 16/11/2015 13262 <1> ; 15/11/2015 13263 <1> ; 24/10/2015 13264 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 13265 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 13266 <1> ; < serial port 1 interrupt handler > 13267 <1> ; 13268 00002A70 FEC6 <1> inc dh ; 3FAh ; COM1 Interrupt id. register 13269 <1> com_i0: 13270 <1> ;push eax ; * 13271 <1> ; 07/11/2015 13272 00002A72 A2[D6670000] <1> mov byte [ccomport], al 13273 <1> ; 09/11/2015 13274 <1> ;movzx ebx, ax ; 8 or 9 13275 <1> ; 08/01/2022 13276 00002A77 89C3 <1> mov ebx, eax ; 8 or 9 13277 <1> ; 17/11/2015 13278 <1> ; reset request for response status 13279 00002A79 88A3[CC670000] <1> mov [ebx+req_resp-8], ah ; 0 13280 <1> ; 13281 <1> ; 20/11/2015 13282 00002A7F EC <1> in al, dx ; read interrupt id. register 13283 00002A80 EB00 <1> JMP $+2 ; I/O DELAY 13284 00002A82 2404 <1> and al, 4 ; received data available? 13285 00002A84 7470 <1> jz short com_eoi ; (transmit. holding reg. empty) 13286 <1> ; 13287 <1> ; 20/11/2015 13288 00002A86 80EA02 <1> sub dl, 3FAh-3F8h ; data register (3F8h, 2F8h) 13289 00002A89 EC <1> in al, dx ; read character 13290 <1> ;JMP $+2 ; I/O DELAY 13291 <1> ; 08/11/2015 13292 <1> ; 07/11/2015 13293 00002A8A 89DE <1> mov esi, ebx 13294 00002A8C 89DF <1> mov edi, ebx 13295 00002A8E 81C6[D0670000] <1> add esi, rchar - 8 ; points to last received char 13296 00002A94 81C7[D2670000] <1> add edi, schar - 8 ; points to last sent char 13297 00002A9A 8806 <1> mov [esi], al ; received char (current char) 13298 <1> ; query 13299 00002A9C 20C0 <1> and al, al 13300 00002A9E 7527 <1> jnz short com_i2 13301 <1> ; response 13302 <1> ; 17/11/2015 13303 <1> ; set request for response status 13304 00002AA0 FE83[CC670000] <1> inc byte [ebx+req_resp-8] ; 1 13305 <1> ; 13306 00002AA6 6683C205 <1> add dx, 3FDh-3F8h ; (3FDh, 2FDh) 13307 00002AAA EC <1> in al, dx ; read line status register 13308 00002AAB EB00 <1> JMP $+2 ; I/O DELAY 13309 00002AAD 2420 <1> and al, 20h ; transmitter holding reg. empty? 13310 00002AAF 7445 <1> jz short com_eoi ; no 13311 00002AB1 B0FF <1> mov al, 0FFh ; response 13312 00002AB3 6683EA05 <1> sub dx, 3FDh-3F8h ; data port (3F8h, 2F8h) 13313 00002AB7 EE <1> out dx, al ; send on serial port 13314 <1> ; 17/11/2015 13315 00002AB8 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 13316 00002ABB 7502 <1> jne short com_i1 ; no 13317 00002ABD 8807 <1> mov [edi], al ; 0FFh (responded) 13318 <1> com_i1: 13319 <1> ; 17/11/2015 13320 <1> ; reset request for response status (again) 13321 00002ABF FE8B[CC670000] <1> dec byte [ebx+req_resp-8] ; 0 13322 00002AC5 EB2F <1> jmp short com_eoi 13323 <1> com_i2: 13324 <1> ; 08/11/2015 13325 00002AC7 3CFF <1> cmp al, 0FFh ; (response ?) 13326 00002AC9 7417 <1> je short com_i3 ; (check for response signal) 13327 <1> ; 07/11/2015 13328 00002ACB 3C04 <1> cmp al, 04h ; EOT 13329 00002ACD 751C <1> jne short com_i4 13330 <1> ; EOT = 04h (End of Transmit) - 'CTRL + D' 13331 <1> ;(an EOT char is supposed as a ctrl+brk from the terminal) 13332 <1> ; 08/11/2015 13333 <1> ; ptty -> tty 0 to 7 (pseudo screens) 13334 00002ACF 861D[96670000] <1> xchg bl, [ptty] ; tty number (8 or 9) 13335 00002AD5 E80BFFFFFF <1> call ctrlbrk 13336 00002ADA 861D[96670000] <1> xchg [ptty], bl ; (restore ptty value and BL value) 13337 <1> ;mov al, 04h ; EOT 13338 <1> ; 08/11/2015 13339 00002AE0 EB09 <1> jmp short com_i4 13340 <1> com_i3: 13341 <1> ; 08/11/2015 13342 <1> ; If 0FFh has been received just after a query 13343 <1> ; (schar, ZERO), it is a response signal. 13344 <1> ; 17/11/2015 13345 00002AE2 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 13346 00002AE5 7704 <1> ja short com_i4 ; no 13347 <1> ; reset query status (schar) 13348 00002AE7 8807 <1> mov [edi], al ; 0FFh 13349 00002AE9 FEC0 <1> inc al ; 0 13350 <1> com_i4: 13351 <1> ; 27/07/2014 13352 <1> ; 09/07/2014 13353 00002AEB D0E3 <1> shl bl, 1 13354 00002AED 81C3[98670000] <1> add ebx, ttychr 13355 <1> ; 23/07/2014 (always overwrite) 13356 <1> ;;cmp word [ebx], 0 13357 <1> ;;ja short com_eoi 13358 <1> ; 13359 00002AF3 668903 <1> mov [ebx], ax ; Save ascii code 13360 <1> ; scan code = 0 13361 <1> com_eoi: 13362 <1> ;mov al, 20h 13363 <1> ;out 20h, al ; end of interrupt 13364 <1> ; 13365 <1> ; 07/11/2015 13366 <1> ;pop eax ; * 13367 00002AF6 A0[D6670000] <1> mov al, byte [ccomport] ; current COM port 13368 <1> ; al = tty number (8 or 9) 13369 00002AFB E8521C0000 <1> call wakeup 13370 <1> com_iret: 13371 <1> ; 23/10/2015 13372 00002B00 5A <1> pop edx ; ** 13373 00002B01 59 <1> pop ecx ; *** 13374 <1> ; 18/11/2015 13375 <1> ;pop eax ; **** 13376 <1> ;mov cr3, eax 13377 <1> ;jmp iiret 13378 00002B02 E995DEFFFF <1> jmp iiretp 13379 <1> 13380 <1> ;iiretp: ; 01/09/2015 13381 <1> ; ; 28/08/2015 13382 <1> ; pop eax ; (*) page directory 13383 <1> ; mov cr3, eax 13384 <1> ;iiret: 13385 <1> ; ; 22/08/2014 13386 <1> ; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 13387 <1> ; out 20h, al ; 8259 PORT 13388 <1> ; ; 13389 <1> ; pop es 13390 <1> ; pop ds 13391 <1> ; pop edi 13392 <1> ; pop esi 13393 <1> ; pop ebx ; 29/08/2014 13394 <1> ; pop eax 13395 <1> ; iretd 13396 <1> 13397 <1> sp_init: 13398 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 13399 <1> ; 07/11/2015 13400 <1> ; 29/10/2015 13401 <1> ; 26/10/2015 13402 <1> ; 23/10/2015 13403 <1> ; 29/06/2015 13404 <1> ; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud) 13405 <1> ; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud) 13406 <1> ; Initialization of Serial Port Communication Parameters 13407 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 13408 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 13409 <1> ; 13410 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 13411 <1> ; 13412 <1> ; INPUT: (29/06/2015) 13413 <1> ; AL = 0 for COM1 13414 <1> ; 1 for COM2 13415 <1> ; AH = Communication parameters 13416 <1> ; 13417 <1> ; (*) Communication parameters (except BAUD RATE): 13418 <1> ; Bit 4 3 2 1 0 13419 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 13420 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 13421 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 13422 <1> ; 11 = even 13423 <1> ; Baud rate setting bits: (29/06/2015) 13424 <1> ; Retro UNIX 386 v1 feature only ! 13425 <1> ; Bit 7 6 5 | Baud rate 13426 <1> ; ------------------------ 13427 <1> ; value 0 0 0 | Default (Divisor = 1) 13428 <1> ; 0 0 1 | 9600 (12) 13429 <1> ; 0 1 0 | 19200 (6) 13430 <1> ; 0 1 1 | 38400 (3) 13431 <1> ; 1 0 0 | 14400 (8) 13432 <1> ; 1 0 1 | 28800 (4) 13433 <1> ; 1 1 0 | 57600 (2) 13434 <1> ; 1 1 1 | 115200 (1) 13435 <1> 13436 <1> ; References: 13437 <1> ; (1) IBM PC-XT Model 286 BIOS Source Code 13438 <1> ; RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232) 13439 <1> ; (2) Award BIOS 1999 - ATORGS.ASM 13440 <1> ; (3) http://wiki.osdev.org/Serial_Ports 13441 <1> ; 13442 <1> ; Set communication parameters for COM1 (= 03h) 13443 <1> ; 13444 00002B07 BB[D2670000] <1> mov ebx, com1p ; COM1 parameters 13445 00002B0C 66BAF803 <1> mov dx, 3F8h ; COM1 13446 <1> ; 29/10/2015 13447 00002B10 66B90103 <1> mov cx, 301h ; divisor = 1 (115200 baud) 13448 00002B14 E84F000000 <1> call sp_i3 ; call A4 13449 00002B19 A880 <1> test al, 80h 13450 00002B1B 740E <1> jz short sp_i0 ; OK.. 13451 <1> ; Error ! 13452 <1> ;mov dx, 3F8h 13453 00002B1D 80EA05 <1> sub dl, 5 ; 3FDh -> 3F8h 13454 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 13455 <1> ; 08/01/2022 13456 00002B20 B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 13457 00002B22 E841000000 <1> call sp_i3 ; call A4 13458 00002B27 A880 <1> test al, 80h 13459 00002B29 7508 <1> jnz short sp_i1 13460 <1> sp_i0: 13461 <1> ; (Note: Serial port interrupts will be disabled here...) 13462 <1> ; (INT 14h initialization code disables interrupts.) 13463 <1> ; 13464 00002B2B C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 13465 00002B2E E8BF000000 <1> call sp_i5 ; 29/06/2015 13466 <1> sp_i1: 13467 00002B33 43 <1> inc ebx 13468 00002B34 66BAF802 <1> mov dx, 2F8h ; COM2 13469 <1> ; 29/10/2015 13470 <1> ;mov cx, 301h ; divisor = 1 (115200 baud) 13471 <1> ; 08/01/2022 13472 00002B38 B101 <1> mov cl, 01h ; cx = 301h, divisor = 1 (115200 baud) 13473 00002B3A E829000000 <1> call sp_i3 ; call A4 13474 00002B3F A880 <1> test al, 80h 13475 00002B41 740E <1> jz short sp_i2 ; OK.. 13476 <1> ; Error ! 13477 <1> ;mov dx, 2F8h 13478 00002B43 80EA05 <1> sub dl, 5 ; 2FDh -> 2F8h 13479 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 13480 <1> ; 08/01/2022 13481 00002B46 B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 13482 00002B48 E81B000000 <1> call sp_i3 ; call A4 13483 00002B4D A880 <1> test al, 80h 13484 00002B4F 7516 <1> jnz short sp_i7 13485 <1> sp_i2: 13486 00002B51 C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 13487 <1> sp_i6: 13488 <1> ;; COM2 - enabling IRQ 3 13489 <1> ; 08/01/2022 13490 00002B54 B4F7 <1> mov ah, 0F7h ; enable IRQ 3 (COM2) 13491 <1> ; 07/11/2015 13492 <1> ; 26/10/2015 13493 <1> ;pushf 13494 <1> ;cli 13495 <1> ;; 13496 <1> ;;mov dx, 2FCh ; modem control register 13497 <1> ;mov dl, 0FCh ; 08/01/2022 13498 <1> ;in al, dx ; read register 13499 <1> ;JMP $+2 ; I/O DELAY 13500 <1> ;or al, 8 ; enable bit 3 (OUT2) 13501 <1> ;out dx, al ; write back to register 13502 <1> ;JMP $+2 ; I/O DELAY 13503 <1> ;;mov dx, 2F9h ; interrupt enable register 13504 <1> ;mov dl, 0F9h ; 08/01/2022 13505 <1> ;in al, dx ; read register 13506 <1> ;JMP $+2 ; I/O DELAY 13507 <1> ;;or al, 1 ; receiver data interrupt enable and 13508 <1> ;or al, 3 ; transmitter empty interrupt enable 13509 <1> ;out dx, al ; write back to register 13510 <1> ;JMP $+2 ; I/O DELAY 13511 <1> ;in al, 21h ; read interrupt mask register 13512 <1> ;JMP $+2 ; I/O DELAY 13513 <1> ;and al, 0F7h ; enable IRQ 3 (COM2) 13514 <1> ;out 21h, al ; write back to register 13515 <1> ; 13516 <1> ; 08/01/2022 13517 00002B56 9C <1> pushf 13518 00002B57 E8AA000000 <1> call sp_i8 13519 <1> ; 23/10/2015 13520 00002B5C B8[3B2A0000] <1> mov eax, com2_int 13521 00002B61 A3[58300000] <1> mov [com2_irq3], eax 13522 <1> ; 26/10/2015 13523 00002B66 9D <1> popf 13524 <1> sp_i7: 13525 00002B67 C3 <1> retn 13526 <1> 13527 <1> sp_i3: 13528 <1> ;A4: ;----- INITIALIZE THE COMMUNICATIONS PORT 13529 <1> ; 28/10/2015 13530 00002B68 FEC2 <1> inc dl ; 3F9h (2F9h) ; 3F9h, COM1 Interrupt enable register 13531 00002B6A B000 <1> mov al, 0 13532 00002B6C EE <1> out dx, al ; disable serial port interrupt 13533 00002B6D EB00 <1> JMP $+2 ; I/O DELAY 13534 00002B6F 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; COM1 Line control register (3FBh) 13535 00002B72 B080 <1> mov al, 80h 13536 00002B74 EE <1> out dx, al ; SET DLAB=1 ; divisor latch access bit 13537 <1> ;----- SET BAUD RATE DIVISOR 13538 <1> ; 26/10/2015 13539 00002B75 80EA03 <1> sub dl, 3 ; 3F8h (2F8h) ; register for least significant byte 13540 <1> ; of the divisor value 13541 00002B78 88C8 <1> mov al, cl ; 1 13542 00002B7A EE <1> out dx, al ; 1 = 115200 baud (Retro UNIX 386 v1) 13543 <1> ; 2 = 57600 baud 13544 <1> ; 3 = 38400 baud 13545 <1> ; 6 = 19200 baud 13546 <1> ; 12 = 9600 baud (Retro UNIX 8086 v1) 13547 00002B7B EB00 <1> JMP $+2 ; I/O DELAY 13548 00002B7D 28C0 <1> sub al, al 13549 00002B7F FEC2 <1> inc dl ; 3F9h (2F9h) ; register for most significant byte 13550 <1> ; of the divisor value 13551 00002B81 EE <1> out dx, al ; 0 13552 00002B82 EB00 <1> JMP $+2 ; I/O DELAY 13553 <1> ; 13554 00002B84 88E8 <1> mov al, ch ; 3 ; 8 data bits, 1 stop bit, no parity 13555 <1> ;and al, 1Fh ; Bits 0,1,2,3,4 13556 00002B86 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; Line control register 13557 00002B89 EE <1> out dx, al 13558 00002B8A EB00 <1> JMP $+2 ; I/O DELAY 13559 <1> ; 29/10/2015 13560 00002B8C FECA <1> dec dl ; 3FAh (2FAh) ; FIFO Control register (16550/16750) 13561 00002B8E 30C0 <1> xor al, al ; 0 13562 00002B90 EE <1> out dx, al ; Disable FIFOs (reset to 8250 mode) 13563 00002B91 EB00 <1> JMP $+2 13564 <1> sp_i4: 13565 <1> ;A18: ;----- COMM PORT STATUS ROUTINE 13566 <1> ; 29/06/2015 (line status after modem status) 13567 00002B93 80C204 <1> add dl, 4 ; 3FEh (2FEh) ; Modem status register 13568 <1> sp_i4s: 13569 00002B96 EC <1> in al, dx ; GET MODEM CONTROL STATUS 13570 00002B97 EB00 <1> JMP $+2 ; I/O DELAY 13571 00002B99 88C4 <1> mov ah, al ; PUT IN (AH) FOR RETURN 13572 00002B9B FECA <1> dec dl ; 3FDh (2FDh) ; POINT TO LINE STATUS REGISTER 13573 <1> ; dx = 3FDh for COM1, 2FDh for COM2 13574 00002B9D EC <1> in al, dx ; GET LINE CONTROL STATUS 13575 <1> ; AL = Line status, AH = Modem status 13576 00002B9E C3 <1> retn 13577 <1> 13578 <1> sp_status: 13579 <1> ; 29/06/2015 13580 <1> ; 27/06/2015 (Retro UNIX 386 v1) 13581 <1> ; Get serial port status 13582 00002B9F 66BAFE03 <1> mov dx, 3FEh ; Modem status register (COM1) 13583 00002BA3 28C6 <1> sub dh, al ; dh = 2 for COM2 (al = 1) 13584 <1> ; dx = 2FEh for COM2 13585 00002BA5 EBEF <1> jmp short sp_i4s 13586 <1> 13587 <1> sp_setp: ; Set serial port communication parameters 13588 <1> ; 08/01/2022 13589 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 13590 <1> ; 07/11/2015 13591 <1> ; 29/10/2015 13592 <1> ; 29/06/2015 13593 <1> ; Retro UNIX 386 v1 feature only ! 13594 <1> ; 13595 <1> ; INPUT: 13596 <1> ; AL = 0 for COM1 13597 <1> ; 1 for COM2 13598 <1> ; AH = Communication parameters (*) 13599 <1> ; OUTPUT: 13600 <1> ; CL = Line status 13601 <1> ; CH = Modem status 13602 <1> ; If cf = 1 -> Error code in [u.error] 13603 <1> ; 'invalid parameter !' 13604 <1> ; or 13605 <1> ; 'device not ready !' error 13606 <1> ; 13607 <1> ; (*) Communication parameters (except BAUD RATE): 13608 <1> ; Bit 4 3 2 1 0 13609 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 13610 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 13611 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 13612 <1> ; 11 = even 13613 <1> ; Baud rate setting bits: (29/06/2015) 13614 <1> ; Retro UNIX 386 v1 feature only ! 13615 <1> ; Bit 7 6 5 | Baud rate 13616 <1> ; ------------------------ 13617 <1> ; value 0 0 0 | Default (Divisor = 1) 13618 <1> ; 0 0 1 | 9600 (12) 13619 <1> ; 0 1 0 | 19200 (6) 13620 <1> ; 0 1 1 | 38400 (3) 13621 <1> ; 1 0 0 | 14400 (8) 13622 <1> ; 1 0 1 | 28800 (4) 13623 <1> ; 1 1 0 | 57600 (2) 13624 <1> ; 1 1 1 | 115200 (1) 13625 <1> ; 13626 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 13627 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 13628 <1> ; 13629 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 13630 <1> ; 13631 00002BA7 66BAF803 <1> mov dx, 3F8h 13632 00002BAB BB[D2670000] <1> mov ebx, com1p ; COM1 control byte offset 13633 00002BB0 3C01 <1> cmp al, 1 13634 00002BB2 7770 <1> ja short sp_invp_err 13635 00002BB4 7203 <1> jb short sp_setp1 ; COM1 (AL = 0) 13636 00002BB6 FECE <1> dec dh ; 2F8h 13637 00002BB8 43 <1> inc ebx ; COM2 control byte offset 13638 <1> sp_setp1: 13639 <1> ; 29/10/2015 13640 00002BB9 8823 <1> mov [ebx], ah 13641 00002BBB 0FB6CC <1> movzx ecx, ah 13642 00002BBE C0E905 <1> shr cl, 5 ; -> baud rate index 13643 00002BC1 80E41F <1> and ah, 1Fh ; communication parameters except baud rate 13644 00002BC4 8A81[332C0000] <1> mov al, [ecx+b_div_tbl] 13645 00002BCA 6689C1 <1> mov cx, ax 13646 00002BCD E896FFFFFF <1> call sp_i3 13647 00002BD2 6689C1 <1> mov cx, ax ; CL = Line status, CH = Modem status 13648 00002BD5 A880 <1> test al, 80h 13649 00002BD7 740F <1> jz short sp_setp2 13650 00002BD9 C603E3 <1> mov byte [ebx], 0E3h ; Reset to initial value (11100011b) 13651 <1> stp_dnr_err: 13652 00002BDC C705[186D0000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !' 13653 00002BE4 0000 <1> 13654 <1> ; CL = Line status, CH = Modem status 13655 00002BE6 F9 <1> stc 13656 00002BE7 C3 <1> retn 13657 <1> sp_setp2: 13658 00002BE8 80FE02 <1> cmp dh, 2 ; COM2 (2F?h) 13659 <1> ;jna sp_i6 13660 <1> ; COM1 (3F?h) 13661 <1> ; 24/12/2021 13662 00002BEB 7705 <1> ja short sp_i5 13663 00002BED E962FFFFFF <1> jmp sp_i6 13664 <1> sp_i5: 13665 <1> ; 08/01/2022 13666 00002BF2 B4EF <1> mov ah, 0EFh ; enable IRQ 4 (COM1) 13667 <1> ; 07/11/2015 13668 <1> ; 26/10/2015 13669 <1> ; 29/06/2015 13670 <1> ; 13671 <1> ;; COM1 - enabling IRQ 4 13672 <1> ;pushf 13673 <1> ;cli 13674 <1> ;;mov dx, 3FCh ; modem control register 13675 <1> ;mov dl, 0FCh ; 08/01/2022 13676 <1> ;in al, dx ; read register 13677 <1> ;JMP $+2 ; I/O DELAY 13678 <1> ;or al, 8 ; enable bit 3 (OUT2) 13679 <1> ;out dx, al ; write back to register 13680 <1> ;JMP $+2 ; I/O DELAY 13681 <1> ;;mov dx, 3F9h ; interrupt enable register 13682 <1> ;mov dl, 0F9h ; 08/01/2022 13683 <1> ;in al, dx ; read register 13684 <1> ;JMP $+2 ; I/O DELAY 13685 <1> ;;or al, 1 ; receiver data interrupt enable and 13686 <1> ;or al, 3 ; transmitter empty interrupt enable 13687 <1> ;out dx, al ; write back to register 13688 <1> ;JMP $+2 ; I/O DELAY 13689 <1> ;in al, 21h ; read interrupt mask register 13690 <1> ;JMP $+2 ; I/O DELAY 13691 <1> ;and al, 0EFh ; enable IRQ 4 (COM1) 13692 <1> ;out 21h, al ; write back to register 13693 <1> ; 13694 <1> ; 08/01/2022 13695 00002BF4 9C <1> pushf 13696 00002BF5 E80C000000 <1> call sp_i8 13697 <1> ; 23/10/2015 13698 00002BFA B8[442A0000] <1> mov eax, com1_int 13699 00002BFF A3[54300000] <1> mov [com1_irq4], eax 13700 <1> ; 26/10/2015 13701 00002C04 9D <1> popf 13702 00002C05 C3 <1> retn 13703 <1> 13704 <1> sp_i8: 13705 <1> ; 08/01/2022 13706 <1> ;pushf 13707 00002C06 FA <1> cli 13708 <1> ; 13709 <1> ;mov dx, 2FCh ; 3FCh ; modem control register 13710 00002C07 B2FC <1> mov dl, 0FCh 13711 00002C09 EC <1> in al, dx ; read register 13712 00002C0A EB00 <1> JMP $+2 ; I/O DELAY 13713 00002C0C 0C08 <1> or al, 8 ; enable bit 3 (OUT2) 13714 00002C0E EE <1> out dx, al ; write back to register 13715 00002C0F EB00 <1> JMP $+2 ; I/O DELAY 13716 <1> ;mov dx, 2F9h ; 3F9h ; interrupt enable register 13717 00002C11 B2F9 <1> mov dl, 0F9h 13718 00002C13 EC <1> in al, dx ; read register 13719 00002C14 EB00 <1> JMP $+2 ; I/O DELAY 13720 <1> ;or al, 1 ; receiver data interrupt enable and 13721 00002C16 0C03 <1> or al, 3 ; transmitter empty interrupt enable 13722 00002C18 EE <1> out dx, al ; write back to register 13723 00002C19 EB00 <1> JMP $+2 ; I/O DELAY 13724 00002C1B E421 <1> in al, 21h ; read interrupt mask register 13725 00002C1D EB00 <1> JMP $+2 ; I/O DELAY 13726 <1> ;and al, 0F7h ; 0EFh ; enable IRQ 3 (COM2) 13727 00002C1F 20E0 <1> and al, ah ; 0F7h or 0EFh 13728 00002C21 E621 <1> out 21h, al ; write back to register 13729 <1> ; 13730 <1> ;popf 13731 00002C23 C3 <1> retn 13732 <1> 13733 <1> sp_invp_err: 13734 00002C24 C705[186D0000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 13735 00002C2C 0000 <1> 13736 00002C2E 31C9 <1> xor ecx, ecx 13737 00002C30 49 <1> dec ecx ; 0FFFFh 13738 00002C31 F9 <1> stc 13739 00002C32 C3 <1> retn 13740 <1> 13741 <1> ; 29/10/2015 13742 <1> b_div_tbl: ; Baud rate divisor table (115200/divisor) 13743 00002C33 010C0603080401 <1> db 1, 12, 6, 3, 8, 4, 1 13744 <1> 13745 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 13746 <1> epoch: 13747 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 13748 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 13749 <1> ; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM) 13750 <1> ; 'epoch' procedure prototype: 13751 <1> ; UNIXCOPY.ASM, 10/03/2013 13752 <1> ; 14/11/2012 13753 <1> ; unixboot.asm (boot file configuration) 13754 <1> ; version of "epoch" procedure in "unixproc.asm" 13755 <1> ; 21/7/2012 13756 <1> ; 15/7/2012 13757 <1> ; 14/7/2012 13758 <1> ; Erdogan Tan - RETRO UNIX v0.1 13759 <1> ; compute current date and time as UNIX Epoch/Time 13760 <1> ; UNIX Epoch: seconds since 1/1/1970 00:00:00 13761 <1> ; 13762 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 13763 <1> ; 13764 00002C3A E818010000 <1> call get_rtc_time ; Return Current Time 13765 00002C3F 86E9 <1> xchg ch,cl 13766 00002C41 66890D[D8640000] <1> mov [hour], cx 13767 00002C48 86F2 <1> xchg dh,dl 13768 00002C4A 668915[DA640000] <1> mov [second], dx 13769 <1> ; 13770 00002C51 E832010000 <1> call get_rtc_date ; Return Current Date 13771 00002C56 86E9 <1> xchg ch,cl 13772 00002C58 66890D[D4640000] <1> mov [year], cx 13773 00002C5F 86F2 <1> xchg dh,dl 13774 00002C61 668915[D6640000] <1> mov [month], dx 13775 <1> ; 13776 00002C68 66B93030 <1> mov cx, 3030h 13777 <1> ; 13778 00002C6C A0[D8640000] <1> mov al, [hour] ; Hour 13779 <1> ; AL <= BCD number) 13780 00002C71 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13781 <1> ; AH = AL / 10h 13782 <1> ; AL = AL MOD 10h 13783 00002C73 D50A <1> aad ; AX= AH*10+AL 13784 00002C75 A2[D8640000] <1> mov [hour], al 13785 00002C7A A0[D9640000] <1> mov al, [hour+1] ; Minute 13786 <1> ; AL <= BCD number) 13787 00002C7F D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13788 <1> ; AH = AL / 10h 13789 <1> ; AL = AL MOD 10h 13790 00002C81 D50A <1> aad ; AX= AH*10+AL 13791 00002C83 A2[D9640000] <1> mov [minute], al 13792 00002C88 A0[DA640000] <1> mov al, [second] ; Second 13793 <1> ; AL <= BCD number) 13794 00002C8D D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13795 <1> ; AH = AL / 10h 13796 <1> ; AL = AL MOD 10h 13797 00002C8F D50A <1> aad ; AX= AH*10+AL 13798 00002C91 A2[DA640000] <1> mov [second], al 13799 00002C96 66A1[D4640000] <1> mov ax, [year] ; Year (century) 13800 <1> ;push ax 13801 <1> ; 04/12/2021 13802 00002C9C 50 <1> push eax 13803 <1> ; AL <= BCD number) 13804 00002C9D D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13805 <1> ; AH = AL / 10h 13806 <1> ; AL = AL MOD 10h 13807 00002C9F D50A <1> aad ; AX= AH*10+AL 13808 00002CA1 B464 <1> mov ah, 100 13809 00002CA3 F6E4 <1> mul ah 13810 00002CA5 66A3[D4640000] <1> mov [year], ax 13811 <1> ;pop ax 13812 <1> ; 04/12/2021 13813 00002CAB 58 <1> pop eax 13814 00002CAC 88E0 <1> mov al, ah 13815 <1> ; AL <= BCD number) 13816 00002CAE D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13817 <1> ; AH = AL / 10h 13818 <1> ; AL = AL MOD 10h 13819 00002CB0 D50A <1> aad ; AX= AH*10+AL 13820 00002CB2 660105[D4640000] <1> add [year], ax 13821 00002CB9 A0[D6640000] <1> mov al, [month] ; Month 13822 <1> ; AL <= BCD number) 13823 00002CBE D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13824 <1> ; AH = AL / 10h 13825 <1> ; AL = AL MOD 10h 13826 00002CC0 D50A <1> aad ; AX= AH*10+AL 13827 00002CC2 A2[D6640000] <1> mov [month], al 13828 00002CC7 A0[D7640000] <1> mov al, [month+1] ; Day 13829 <1> ; AL <= BCD number) 13830 00002CCC D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13831 <1> ; AH = AL / 10h 13832 <1> ; AL = AL MOD 10h 13833 00002CCE D50A <1> aad ; AX= AH*10+AL 13834 00002CD0 A2[D7640000] <1> mov [day], al 13835 <1> 13836 <1> _epoch: 13837 <1> ; 17/07/2022 13838 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification) 13839 <1> ; 09/04/2013 (Retro UNIX 8086 v1) 13840 <1> ; 13841 <1> ; ((Modified registers: EAX, EDX, EBX)) 13842 <1> ; 13843 <1> ; Derived from DALLAS Semiconductor 13844 <1> ; Application Note 31 (DS1602/DS1603) 13845 <1> ; 6 May 1998 13846 00002CD5 29C0 <1> sub eax, eax 13847 00002CD7 66A1[D4640000] <1> mov ax, [year] 13848 00002CDD 662DB207 <1> sub ax, 1970 13849 00002CE1 BA6D010000 <1> mov edx, 365 13850 00002CE6 F7E2 <1> mul edx 13851 00002CE8 31DB <1> xor ebx, ebx 13852 00002CEA 8A1D[D6640000] <1> mov bl, [month] 13853 00002CF0 FECB <1> dec bl 13854 00002CF2 D0E3 <1> shl bl, 1 13855 <1> ;sub edx, edx 13856 00002CF4 668B93[DC640000] <1> mov dx, [EBX+DMonth] 13857 00002CFB 8A1D[D7640000] <1> mov bl, [day] 13858 00002D01 FECB <1> dec bl 13859 00002D03 01D0 <1> add eax, edx 13860 00002D05 01D8 <1> add eax, ebx 13861 <1> ; EAX = days since 1/1/1970 13862 00002D07 668B15[D4640000] <1> mov dx, [year] 13863 00002D0E 6681EAB107 <1> sub dx, 1969 13864 <1> ;shr dx, 1 13865 <1> ;shr dx, 1 13866 <1> ; 17/07/2022 13867 00002D13 C1EA02 <1> shr edx, 2 13868 <1> ; (year-1969)/4 13869 00002D16 01D0 <1> add eax, edx 13870 <1> ; + leap days since 1/1/1970 13871 00002D18 803D[D6640000]02 <1> cmp byte [month], 2 ; if past february 13872 00002D1F 7610 <1> jna short cte1 13873 00002D21 668B15[D4640000] <1> mov dx, [year] 13874 00002D28 6683E203 <1> and dx, 3 ; year mod 4 13875 00002D2C 7503 <1> jnz short cte1 13876 <1> ; and if leap year 13877 00002D2E 83C001 <1> add eax, 1 ; add this year's leap day (february 29) 13878 <1> cte1: ; compute seconds since 1/1/1970 13879 00002D31 BA18000000 <1> mov edx, 24 13880 00002D36 F7E2 <1> mul edx 13881 00002D38 8A15[D8640000] <1> mov dl, [hour] 13882 00002D3E 01D0 <1> add eax, edx 13883 <1> ; EAX = hours since 1/1/1970 00:00:00 13884 <1> ;mov ebx, 60 13885 00002D40 B33C <1> mov bl, 60 13886 00002D42 F7E3 <1> mul ebx 13887 00002D44 8A15[D9640000] <1> mov dl, [minute] 13888 00002D4A 01D0 <1> add eax, edx 13889 <1> ; EAX = minutes since 1/1/1970 00:00:00 13890 <1> ;mov ebx, 60 13891 00002D4C F7E3 <1> mul ebx 13892 00002D4E 8A15[DA640000] <1> mov dl, [second] 13893 00002D54 01D0 <1> add eax, edx 13894 <1> ; EAX -> seconds since 1/1/1970 00:00:00 13895 00002D56 C3 <1> retn 13896 <1> 13897 <1> get_rtc_time: 13898 <1> ; 15/03/2015 13899 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 13900 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 13901 <1> ; INT 1Ah 13902 <1> ; (AH) = 02H READ THE REAL TIME CLOCK AND RETURN WITH, : 13903 <1> ; (CH) = HOURS IN BCD (00-23) : 13904 <1> ; (CL) = MINUTES IN BCD (00-59) : 13905 <1> ; (DH) = SECONDS IN BCD (00-59) : 13906 <1> ; (DL) = DAYLIGHT SAVINGS ENABLE (00-01). : 13907 <1> ; 13908 <1> RTC_20: ; GET RTC TIME 13909 00002D57 FA <1> cli 13910 00002D58 E8DBDDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 13911 00002D5D 7227 <1> JC short RTC_29 ; EXIT IF ERROR (CY= 1) 13912 <1> 13913 00002D5F B000 <1> MOV AL, CMOS_SECONDS ; SET ADDRESS OF SECONDS 13914 00002D61 E8BCDDFFFF <1> CALL CMOS_READ ; GET SECONDS 13915 00002D66 88C6 <1> MOV DH, AL ; SAVE 13916 00002D68 B00B <1> MOV AL, CMOS_REG_B ; ADDRESS ALARM REGISTER 13917 00002D6A E8B3DDFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 13918 00002D6F 2401 <1> AND AL, 00000001B ; MASK FOR VALID DSE BIT 13919 00002D71 88C2 <1> MOV DL, AL ; SET [DL] TO ZERO FOR NO DSE BIT 13920 00002D73 B002 <1> MOV AL, CMOS_MINUTES ; SET ADDRESS OF MINUTES 13921 00002D75 E8A8DDFFFF <1> CALL CMOS_READ ; GET MINUTES 13922 00002D7A 88C1 <1> MOV CL, AL ; SAVE 13923 00002D7C B004 <1> MOV AL, CMOS_HOURS ; SET ADDRESS OF HOURS 13924 00002D7E E89FDDFFFF <1> CALL CMOS_READ ; GET HOURS 13925 00002D83 88C5 <1> MOV CH, AL ; SAVE 13926 00002D85 F8 <1> CLC ; SET CY= 0 13927 <1> RTC_29: 13928 00002D86 FB <1> sti 13929 00002D87 C3 <1> RETn ; RETURN WITH RESULT IN CARRY FLAG 13930 <1> 13931 <1> get_rtc_date: 13932 <1> ; 15/03/2015 13933 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 13934 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 13935 <1> ; INT 1Ah 13936 <1> ; (AH) = 04H READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,: 13937 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 13938 <1> ; (CL) = YEAR IN BCD (00-99) : 13939 <1> ; (DH) = MONTH IN BCD (01-12) : 13940 <1> ; (DL) = DAY IN BCD (01-31). 13941 <1> ; 13942 <1> RTC_40: ; GET RTC DATE 13943 00002D88 FA <1> cli 13944 00002D89 E8AADDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 13945 00002D8E 7225 <1> JC short RTC_49 ; EXIT IF ERROR (CY= 1) 13946 <1> 13947 00002D90 B007 <1> MOV AL, CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH 13948 00002D92 E88BDDFFFF <1> CALL CMOS_READ ; READ DAY OF MONTH 13949 00002D97 88C2 <1> MOV DL, AL ; SAVE 13950 00002D99 B008 <1> MOV AL, CMOS_MONTH ; ADDRESS MONTH 13951 00002D9B E882DDFFFF <1> CALL CMOS_READ ; READ MONTH 13952 00002DA0 88C6 <1> MOV DH, AL ; SAVE 13953 00002DA2 B009 <1> MOV AL, CMOS_YEAR ; ADDRESS YEAR 13954 00002DA4 E879DDFFFF <1> CALL CMOS_READ ; READ YEAR 13955 00002DA9 88C1 <1> MOV CL, AL ; SAVE 13956 00002DAB B032 <1> MOV AL, CMOS_CENTURY ; ADDRESS CENTURY LOCATION 13957 00002DAD E870DDFFFF <1> CALL CMOS_READ ; GET CENTURY BYTE 13958 00002DB2 88C5 <1> MOV CH, AL ; SAVE 13959 00002DB4 F8 <1> CLC ; SET CY=0 13960 <1> RTC_49: 13961 00002DB5 FB <1> sti 13962 00002DB6 C3 <1> RETn ; RETURN WITH RESULTS IN CARRY FLAG 13963 <1> 13964 <1> set_date_time: 13965 <1> convert_from_epoch: 13966 <1> ; 02/06/2022 (BugFix) 13967 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 13968 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 13969 <1> ; 'convert_from_epoch' procedure prototype: 13970 <1> ; UNIXCOPY.ASM, 10/03/2013 13971 <1> ; 13972 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 13973 <1> ; 13974 <1> ; Derived from DALLAS Semiconductor 13975 <1> ; Application Note 31 (DS1602/DS1603) 13976 <1> ; 6 May 1998 13977 <1> ; 13978 <1> ; INPUT: 13979 <1> ; EAX = Unix (Epoch) Time 13980 <1> ; 13981 00002DB7 31D2 <1> xor edx, edx 13982 <1> ; 02/06/2022 13983 00002DB9 31C9 <1> xor ecx, ecx 13984 00002DBB 31DB <1> xor ebx, ebx 13985 <1> ;mov ecx, 60 13986 00002DBD B13C <1> mov cl, 60 13987 00002DBF F7F1 <1> div ecx 13988 <1> ;mov [imin], eax ; whole minutes 13989 <1> ; since 1/1/1970 13990 <1> ;mov [second], dx ; leftover seconds 13991 00002DC1 8815[DA640000] <1> mov [second], dl ; 02/06/2022 13992 00002DC7 29D2 <1> sub edx, edx 13993 00002DC9 F7F1 <1> div ecx 13994 <1> ;mov [ihrs], eax ; whole hours 13995 <1> ; ; since 1/1/1970 13996 <1> ;mov [minute], dx ; leftover minutes 13997 00002DCB 8815[D9640000] <1> mov [minute], dl ; 02/06/2022 13998 00002DD1 31D2 <1> xor edx, edx 13999 <1> ;mov cx, 24 14000 00002DD3 B118 <1> mov cl, 24 14001 00002DD5 F7F1 <1> div ecx 14002 <1> ;mov [iday], ax ; whole days 14003 <1> ; since 1/1/1970 14004 <1> ;mov [hour], dx ; leftover hours 14005 00002DD7 8815[D8640000] <1> mov [hour], dl ; 02/06/2022 14006 <1> 14007 00002DDD 05DB020000 <1> add eax, 365+366 ; whole day since 14008 <1> ; 1/1/1968 14009 <1> ;mov [iday], ax 14010 00002DE2 50 <1> push eax 14011 00002DE3 29D2 <1> sub edx, edx 14012 00002DE5 B9B5050000 <1> mov ecx, (4*365)+1 ; 4 years = 1461 days 14013 00002DEA F7F1 <1> div ecx 14014 00002DEC 59 <1> pop ecx 14015 <1> ;mov [lday], ax ; count of quadyrs (4 years) 14016 <1> ;push dx 14017 <1> ; 02/06/2022 14018 00002DED 52 <1> push edx 14019 <1> ;mov [qday], dx ; days since quadyr began 14020 00002DEE 6683FA3C <1> cmp dx, 31+29 ; if past feb 29 then 14021 00002DF2 F5 <1> cmc ; add this quadyr's leap day 14022 00002DF3 83D000 <1> adc eax, 0 ; to # of qadyrs (leap days) 14023 <1> ;mov [lday], ax ; since 1968 14024 <1> ;mov cx, [iday] 14025 00002DF6 91 <1> xchg ecx, eax ; ECX = lday, EAX = iday 14026 00002DF7 29C8 <1> sub eax, ecx ; iday - lday 14027 00002DF9 B96D010000 <1> mov ecx, 365 14028 00002DFE 31D2 <1> xor edx, edx 14029 <1> ; EAX = iday-lday, EDX = 0 14030 00002E00 F7F1 <1> div ecx 14031 <1> ;mov [iyrs], ax ; whole years since 1968 14032 <1> ;jday = iday - (iyrs*365) - lday 14033 <1> ;mov [jday], dx ; days since 1/1 of current year 14034 <1> ;add eax, 1968 14035 00002E02 6605B007 <1> add ax, 1968 ; compute year 14036 00002E06 66A3[D4640000] <1> mov [year], ax 14037 <1> ;mov cx, dx 14038 <1> ; 02/06/2022 14039 00002E0C 89D1 <1> mov ecx, edx 14040 <1> ;mov dx, [qday] 14041 <1> ;pop dx 14042 <1> ; 02/06/2022 14043 00002E0E 5A <1> pop edx 14044 00002E0F 6681FA6D01 <1> cmp dx, 365 ; if qday <= 365 and qday >= 60 14045 00002E14 7709 <1> ja short cfe1 ; jday = jday +1 14046 00002E16 6683FA3C <1> cmp dx, 60 ; if past 2/29 and leap year then 14047 00002E1A F5 <1> cmc ; add a leap day to the # of whole 14048 00002E1B 6683D100 <1> adc cx, 0 ; days since 1/1 of current year 14049 <1> cfe1: 14050 <1> ;mov [jday], cx 14051 <1> ;mov bx, 12 ; estimate month 14052 <1> ;sub ebx, ebx 14053 <1> ; 02/06/2022 14054 00002E1F B30C <1> mov bl, 12 14055 00002E21 66BA6E01 <1> mov dx, 366 ; mday, max. days since 1/1 is 365 14056 00002E25 6683E003 <1> and ax, 11b ; year mod 4 (and dx, 3) 14057 <1> cfe2: ; Month calculation ; 0 to 11 (11 to 0) 14058 <1> ;cmp cx, dx ; mday = # of days passed from 1/1 14059 <1> ; 02/06/2022 14060 00002E29 39D1 <1> cmp ecx, edx 14061 00002E2B 7319 <1> jnb short cfe3 14062 <1> ;dec bx ; month = month - 1 14063 00002E2D FECB <1> dec bl 14064 <1> ;shl bx, 1 14065 00002E2F D0E3 <1> shl bl, 1 14066 00002E31 668B93[DC640000] <1> mov dx, [ebx+DMonth] ; # elapsed days at 1st of month 14067 <1> ;shr bx, 1 ; bx = month - 1 (0 to 11) 14068 <1> ; 02/06/2022 14069 00002E38 D0EB <1> shr bl, 1 14070 00002E3A 80FB01 <1> cmp bl, 1 14071 <1> ;cmp bx, 1 ; if month > 2 and year mod 4 = 0 14072 00002E3D 76EA <1> jna short cfe2 ; then mday = mday + 1 14073 00002E3F 08C0 <1> or al, al ; if past 2/29 and leap year then 14074 00002E41 75E6 <1> jnz short cfe2 ; add leap day (to mday) 14075 <1> ;inc dx ; mday = mday + 1 14076 00002E43 42 <1> inc edx 14077 00002E44 EBE3 <1> jmp short cfe2 14078 <1> cfe3: 14079 <1> ;inc bx ; -> bx = month, 1 to 12 14080 <1> ; 02/06/2022 14081 00002E46 FEC3 <1> inc bl 14082 <1> ;mov [month], bx 14083 00002E48 881D[D6640000] <1> mov [month], bl 14084 <1> ;sub cx, dx ; day = jday - mday + 1 14085 00002E4E 29D1 <1> sub ecx, edx 14086 <1> ;inc cx 14087 00002E50 FEC1 <1> inc cl 14088 <1> ;mov [day], cx 14089 00002E52 880D[D7640000] <1> mov [day], cl ; 02/06/2022 14090 <1> 14091 <1> ; eax, ebx, ecx, edx is changed at return 14092 <1> ; output -> 14093 <1> ; [year], [month], [day], [hour], [minute], [second] 14094 <1> 14095 <1> ; 02/06/2022 (BugFix) 14096 <1> _set_date: 14097 00002E58 66A1[D4640000] <1> mov ax, [year] 14098 00002E5E B520 <1> mov ch, 20h ; century (bcd) 14099 00002E60 662DD007 <1> sub ax, 2000 14100 00002E64 7306 <1> jnc short set_date 14101 00002E66 B519 <1> mov ch, 19h ; century (bcd) 14102 00002E68 6683C064 <1> add ax, 100 14103 <1> ; 02/06/2022 14104 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 14105 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 14106 <1> set_date: 14107 <1> ;mov al, [year+1] 14108 <1> ;aam ; ah = al / 10, al = al mod 10 14109 <1> ;db 0D5h, 10h ; Undocumented inst. AAD 14110 <1> ; ; AL = AH * 10h + AL 14111 <1> ;mov ch, al ; century (BCD) 14112 <1> ;mov al, [year] 14113 <1> ; al = year (0-99) ; 01/06/2022 14114 00002E6C D40A <1> aam ; ah = al / 10, al = al mod 10 14115 00002E6E D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 14116 <1> ; AL = AH * 10h + AL 14117 00002E70 88C1 <1> mov cl, al ; year (BCD) 14118 00002E72 A0[D6640000] <1> mov al, [month] 14119 00002E77 D40A <1> aam ; ah = al / 10, al = al mod 10 14120 00002E79 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 14121 <1> ; AL = AH * 10h + AL 14122 00002E7B 88C6 <1> mov dh, al ; month (BCD) 14123 00002E7D A0[D7640000] <1> mov al, [day] 14124 00002E82 D40A <1> aam ; ah = al / 10, al = al mod 10 14125 00002E84 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 14126 <1> ; AL = AH * 10h + AL 14127 <1> ; 02/06/2022 (BugFix) 14128 00002E86 88C2 <1> mov dl, al ; day (BCD) 14129 <1> 14130 <1> ; Set real-time clock date 14131 00002E88 E879000000 <1> call set_rtc_date 14132 <1> set_time: 14133 <1> ; Read real-time clock time 14134 <1> ; (get day light saving time bit status) 14135 00002E8D FA <1> cli 14136 00002E8E E8A5DCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 14137 <1> ; cf = 1 -> al = 0 14138 00002E93 7207 <1> jc short stime1 14139 00002E95 B00B <1> MOV AL, CMOS_REG_B ; ADDRESS ALARM REGISTER 14140 00002E97 E886DCFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 14141 <1> stime1: 14142 00002E9C FB <1> sti 14143 00002E9D 2401 <1> AND AL, 00000001B ; MASK FOR VALID DSE BIT 14144 00002E9F 88C2 <1> MOV DL, AL ; SET [DL] TO ZERO FOR NO DSE BIT 14145 <1> ; DL = 1 or 0 (day light saving time) 14146 <1> ; 14147 00002EA1 A0[D8640000] <1> mov al, [hour] 14148 00002EA6 D40A <1> aam ; ah = al / 10, al = al mod 10 14149 00002EA8 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 14150 <1> ; AL = AH * 10h + AL 14151 00002EAA 88C5 <1> mov ch, al ; hour (BCD) 14152 00002EAC A0[D9640000] <1> mov al, [minute] 14153 00002EB1 D40A <1> aam ; ah = al / 10, al = al mod 10 14154 00002EB3 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 14155 <1> ; AL = AH * 10h + AL 14156 00002EB5 88C1 <1> mov cl, al ; minute (BCD) 14157 00002EB7 A0[DA640000] <1> mov al, [second] 14158 00002EBC D40A <1> aam ; ah = al / 10, al = al mod 10 14159 00002EBE D510 <1> db 0D5h,10h ; Undocumented inst. AAD 14160 <1> ; AL = AH * 10h + AL 14161 00002EC0 88C6 <1> mov dh, al ; second (BCD) 14162 <1> 14163 <1> ; Set real-time clock time 14164 <1> ; call set_rtc_time 14165 <1> set_rtc_time: 14166 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 14167 <1> ; 15/03/2015 14168 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 14169 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 14170 <1> ; INT 1Ah 14171 <1> ; (AH) = 03H SET THE REAL TIME CLOCK USING, : 14172 <1> ; (CH) = HOURS IN BCD (00-23) : 14173 <1> ; (CL) = MINUTES IN BCD (00-59) : 14174 <1> ; (DH) = SECONDS IN BCD (00-59) : 14175 <1> ; (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00. : 14176 <1> ; : 14177 <1> ; NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. : 14178 <1> ; (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN : 14179 <1> ; APRIL (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN : 14180 <1> ; OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME. : 14181 <1> ; 14182 <1> RTC_30: ; SET RTC TIME 14183 00002EC2 FA <1> cli 14184 00002EC3 E870DCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 14185 00002EC8 7305 <1> JNC short RTC_35 ; GO AROUND IF CLOCK OPERATING 14186 00002ECA E886000000 <1> CALL RTC_STA ; ELSE TRY INITIALIZING CLOCK 14187 <1> RTC_35: 14188 00002ECF 88F4 <1> MOV AH, DH ; GET TIME BYTE - SECONDS 14189 00002ED1 B000 <1> MOV AL, CMOS_SECONDS ; ADDRESS SECONDS 14190 00002ED3 E89D000000 <1> CALL CMOS_WRITE ; UPDATE SECONDS 14191 00002ED8 88CC <1> MOV AH, CL ; GET TIME BYTE - MINUTES 14192 00002EDA B002 <1> MOV AL, CMOS_MINUTES ; ADDRESS MINUTES 14193 00002EDC E894000000 <1> CALL CMOS_WRITE ; UPDATE MINUTES 14194 00002EE1 88EC <1> MOV AH, CH ; GET TIME BYTE - HOURS 14195 00002EE3 B004 <1> MOV AL, CMOS_HOURS ; ADDRESS HOURS 14196 00002EE5 E88B000000 <1> CALL CMOS_WRITE ; UPDATE ADDRESS 14197 <1> ;MOV AX, X*CMOS_REG_B ; ADDRESS ALARM REGISTER 14198 00002EEA 66B80B0B <1> MOV AX, 257*CMOS_REG_B ; 14199 00002EEE E82FDCFFFF <1> CALL CMOS_READ ; READ CURRENT TIME 14200 00002EF3 2462 <1> AND AL, 01100010B ; MASK FOR VALID BIT POSITIONS 14201 00002EF5 0C02 <1> OR AL, 00000010B ; TURN ON 24 HOUR MODE 14202 00002EF7 80E201 <1> AND DL, 00000001B ; USE ONLY THE DSE BIT 14203 00002EFA 08D0 <1> OR AL, DL ; GET DAY LIGHT SAVINGS TIME BIT (OSE) 14204 00002EFC 86E0 <1> XCHG AH, AL ; PLACE IN WORK REGISTER AND GET ADDRESS 14205 00002EFE E872000000 <1> CALL CMOS_WRITE ; SET NEW ALARM BITS 14206 00002F03 F8 <1> CLC ; SET CY= 0 14207 00002F04 FB <1> sti 14208 00002F05 C3 <1> RETn ; RETURN WITH CY= 0 14209 <1> 14210 <1> set_rtc_date: 14211 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 14212 <1> ; 15/03/2015 14213 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 14214 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 14215 <1> ; INT 1Ah 14216 <1> ; (AH) = 05H SET THE DATE INTO THE REAL TIME CLOCK USING, : 14217 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 14218 <1> ; (CL) = YEAR IN BCD (00-99) : 14219 <1> ; (DH) = MONTH IN BCD (01-12) : 14220 <1> ; (DL) = DAY IN BCD (01-31). 14221 <1> ; 14222 <1> RTC_50: ; SET RTC DATE 14223 00002F06 FA <1> cli 14224 00002F07 E82CDCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 14225 00002F0C 7305 <1> JNC short RTC_55 ; GO AROUND IF NO ERROR 14226 00002F0E E842000000 <1> CALL RTC_STA ; ELSE INITIALIZE CLOCK 14227 <1> RTC_55: 14228 00002F13 66B80600 <1> MOV AX, CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE 14229 00002F17 E859000000 <1> CALL CMOS_WRITE ; LOAD ZEROS TO DAY OF WEEK 14230 00002F1C 88D4 <1> MOV AH, DL ; GET DAY OF MONTH BYTE 14231 00002F1E B007 <1> MOV AL, CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE 14232 00002F20 E850000000 <1> CALL CMOS_WRITE ; WRITE OF DAY OF MONTH REGISTER 14233 00002F25 88F4 <1> MOV AH, DH ; GET MONTH 14234 00002F27 B008 <1> MOV AL, CMOS_MONTH ; ADDRESS MONTH BYTE 14235 00002F29 E847000000 <1> CALL CMOS_WRITE ; WRITE MONTH REGISTER 14236 00002F2E 88CC <1> MOV AH, CL ; GET YEAR BYTE 14237 00002F30 B009 <1> MOV AL, CMOS_YEAR ; ADDRESS YEAR REGISTER 14238 00002F32 E83E000000 <1> CALL CMOS_WRITE ; WRITE YEAR REGISTER 14239 00002F37 88EC <1> MOV AH, CH ; GET CENTURY BYTE 14240 00002F39 B032 <1> MOV AL, CMOS_CENTURY ; ADDRESS CENTURY BYTE 14241 00002F3B E835000000 <1> CALL CMOS_WRITE ; WRITE CENTURY LOCATION 14242 <1> ;MOV AX, X*CMOS_REG_B ; ADDRESS ALARM REGISTER 14243 00002F40 66B80B0B <1> MOV AX, 257*CMOS_REG_B ; 14244 00002F44 E8D9DBFFFF <1> CALL CMOS_READ ; READ CURRENT SETTINGS 14245 00002F49 247F <1> AND AL, 07FH ; CLEAR 'SET BIT' 14246 00002F4B 86E0 <1> XCHG AH, AL ; MOVE TO WORK REGISTER 14247 00002F4D E823000000 <1> CALL CMOS_WRITE ; AND START CLOCK UPDATING 14248 00002F52 F8 <1> CLC ; SET CY= 0 14249 00002F53 FB <1> sti 14250 00002F54 C3 <1> RETn ; RETURN CY=0 14251 <1> 14252 <1> ; 15/03/2015 14253 <1> RTC_STA: ; INITIALIZE REAL TIME CLOCK 14254 00002F55 B426 <1> mov ah, 26h 14255 00002F57 B00A <1> mov al, CMOS_REG_A ; ADDRESS REGISTER A AND LOAD DATA MASK 14256 00002F59 E817000000 <1> CALL CMOS_WRITE ; INITIALIZE STATUS REGISTER A 14257 00002F5E B482 <1> mov ah, 82h 14258 00002F60 B00B <1> mov al, CMOS_REG_B ; SET "SET BIT" FOR CLOCK INITIALIZATION 14259 00002F62 E80E000000 <1> CALL CMOS_WRITE ; AND 24 HOUR MODE TO REGISTER B 14260 00002F67 B00C <1> MOV AL, CMOS_REG_C ; ADDRESS REGISTER C 14261 00002F69 E8B4DBFFFF <1> CALL CMOS_READ ; READ REGISTER C TO INITIALIZE 14262 00002F6E B00D <1> MOV AL, CMOS_REG_D ; ADDRESS REGISTER D 14263 <1> ;CALL CMOS_READ ; READ REGISTER D TO INITIALIZE 14264 <1> ;RETn 14265 <1> ; 06/02/2022 14266 00002F70 E9ADDBFFFF <1> jmp CMOS_READ 14267 <1> 14268 <1> ; 15/03/2015 14269 <1> ; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm) 14270 <1> CMOS_WRITE: ; WRITE (AH) TO LOCATION (AL) 14271 00002F75 9C <1> pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 14272 <1> ;push ax ; SAVE WORK REGISTER VALUES 14273 00002F76 D0C0 <1> rol al, 1 ; MOVE NMI BIT TO LOW POSITION 14274 00002F78 F9 <1> stc ; FORCE NMI BIT ON IN CARRY FLAG 14275 00002F79 D0D8 <1> rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 14276 00002F7B FA <1> cli ; DISABLE INTERRUPTS 14277 00002F7C E670 <1> out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 14278 00002F7E 88E0 <1> mov al, ah ; GET THE DATA BYTE TO WRITE 14279 00002F80 E671 <1> out CMOS_DATA, al ; PLACE IN REQUESTED CMOS LOCATION 14280 00002F82 B01E <1> mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 14281 00002F84 D0D8 <1> rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 14282 00002F86 E670 <1> out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 14283 00002F88 90 <1> nop ; I/O DELAY 14284 00002F89 E471 <1> in al, CMOS_DATA ; OPEN STANDBY LATCH 14285 <1> ;pop ax ; RESTORE WORK REGISTERS 14286 00002F8B 9D <1> popf 14287 00002F8C C3 <1> RETn 14288 <1> 14289 <1> bf_init: 14290 <1> ; 21/03/2022 (Retro UNIX 386 v1.2) 14291 <1> ; 28/11/2021 14292 <1> ; 14/08/2015 14293 <1> ; 02/07/2015 14294 <1> ; 01/07/2015 14295 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 14296 <1> ; Buffer (pointer) initialization ! 14297 <1> ; 14298 <1> ; 17/07/2013 - 24/07/2013 14299 <1> ; Retro UNIX 8086 v1 (U9.ASM) 14300 <1> ; (Retro UNIX 8086 v1 feature only !) 14301 <1> ; 14302 00002F8D BF[346C0000] <1> mov edi, bufp 14303 00002F92 B8[E4970000] <1> mov eax, buffer + (nbuf*520) 14304 00002F97 29D2 <1> sub edx, edx 14305 00002F99 FECA <1> dec dl 14306 00002F9B 31C9 <1> xor ecx, ecx 14307 00002F9D 49 <1> dec ecx 14308 <1> bi0: 14309 00002F9E 2D08020000 <1> sub eax, 520 ; 8 header + 512 data 14310 00002FA3 AB <1> stosd 14311 00002FA4 89C6 <1> mov esi, eax 14312 00002FA6 8916 <1> mov [esi], edx ; 000000FFh 14313 <1> ; Not a valid device sign 14314 00002FA8 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 14315 <1> ; Not a valid block number sign 14316 00002FAB 3D[64770000] <1> cmp eax, buffer 14317 00002FB0 77EC <1> ja short bi0 14318 00002FB2 B8[4C6D0000] <1> mov eax, sb0 14319 00002FB7 AB <1> stosd 14320 00002FB8 B8[546F0000] <1> mov eax, sb1 14321 00002FBD AB <1> stosd 14322 00002FBE 89C6 <1> mov esi, eax ; offset sb1 14323 00002FC0 8916 <1> mov [esi], edx ; 000000FFh 14324 <1> ; Not a valid device sign 14325 00002FC2 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 14326 <1> ; Not a valid block number sign 14327 <1> ; 14/08/2015 14328 <1> ;call rdev_init 14329 <1> ;retn 14330 <1> 14331 <1> ; ----- Root file system initialization 14332 <1> 14333 <1> ; 21/03/2022 - Retro UNIX 386 v1.2 14334 <1> ; (Retro UNIX -runix- v2 file system) 14335 <1> ; 28/11/2021 14336 <1> rdev_init: ; root device, super block buffer initialization 14337 <1> ; 14/08/2015 14338 <1> ; Retro UNIX 386 v1 feature only ! 14339 <1> ; 14340 <1> ; NOTE: Disk partitions (file systems), logical 14341 <1> ; drive initialization, partition's start sector etc. 14342 <1> ; will be coded here, later in 'ldrv_init' 14343 <1> 14344 00002FC5 0FB605[88620000] <1> movzx eax, byte [boot_drv] 14345 <1> rdi_0: 14346 00002FCC 3C80 <1> cmp al, 80h 14347 00002FCE 7202 <1> jb short rdi_1 14348 00002FD0 2C7E <1> sub al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1) 14349 <1> rdi_1: 14350 00002FD2 A2[826C0000] <1> mov [rdev], al 14351 <1> ; 21/03/2022 14352 <1> ;cmp al, 2 14353 <1> ;jnb short rdi_2 14354 00002FD7 08C0 <1> or al, al 14355 00002FD9 7504 <1> jnz short rdi_2 ; hard disk boot 14356 <1> ; floppy disk boot 14357 00002FDB 31D2 <1> xor edx, edx ; device number = 0 14358 <1> ; (& fglags = 0) 14359 <1> ; eax = 0 ; boot sector address = 0 14360 <1> ;jmp short rdi_5 14361 00002FDD EB22 <1> jmp short rdi_4 14362 <1> rdi_2: 14363 <1> ; load masterboot sector 14364 <1> ; to get runix v2 partition's boot sector address 14365 <1> ; 14366 00002FDF BB[5C710000] <1> mov ebx, mbrbuf ; masterboot buffer header addr 14367 <1> ;mov [ebx], eax 14368 00002FE4 8803 <1> mov [ebx], al 14369 <1> ;sub al, al 14370 <1> ;; eax = 0 14371 <1> ;mov [ebx+4], eax ; masterboot sector address 14372 00002FE6 E8E52A0000 <1> call diskio 14373 00002FEB 730A <1> jnc short rdi_3 14374 <1> rdi_err: 14375 00002FED BE[14300000] <1> mov esi, disk_read_err_msg 14376 00002FF2 E9B9F9FFFF <1> jmp key_to_reboot 14377 <1> 14378 <1> rdi_3: 14379 <1> ; [ebx+8] = masterboot buffer (data) address 14380 <1> ;cmp word [ebx+8+510], 0AA55h 14381 <1> ;jc short rdi_err 14382 <1> 14383 00002FF7 8D7308 <1> lea esi, [ebx+8] 14384 00002FFA E82D000000 <1> call runix_p_bs ; return start sector address of 14385 <1> ; retro unix v2 partition in esi 14386 <1> ;;jc short rdi_err ; 'retn' 14387 <1> ;jnc short rdi_4 ; Runix v2 partition not found !? 14388 <1> ; 21/03/2022 14389 <1> ; ((Here, if cf is 1, that means, 14390 <1> ; runix v2 partition not found 14391 <1> ; in the MBR partition table. 14392 <1> ; But, at least, there is a valid 14393 <1> ; runix v2 boot sector on the disk 14394 <1> ; which started the kernel. 14395 <1> ; So, runix v2 boot sector code 14396 <1> ; may -must- be on physical sector 0 14397 <1> ; and then the superblock may be 14398 <1> ; -must be- on physical sector 1.)) 14399 <1> ;sub eax, eax 14400 <1> ; eax = 0 14401 <1> ;rdi_4: 14402 00002FFF 8B13 <1> mov edx, [ebx] ; restore device number in dl 14403 <1> ;rdi_5: 14404 <1> rdi_4: 14405 00003001 BB[4C6D0000] <1> mov ebx, sb0 ; super block buffer (header) 14406 <1> 14407 00003006 40 <1> inc eax ; default sector address of the sb 14408 <1> ; (boot sector address + 1) 14409 <1> 14410 <1> ;mov [ebx], eax 14411 <1> ;mov al, 1 ; eax = 1 14412 <1> ;mov [ebx+4], eax ; super block address on disk 14413 <1> ; 21/03/2022 14414 00003007 8913 <1> mov [ebx], edx ; device number in DL 14415 <1> ; (other bytes -flags- are zero) 14416 00003009 894304 <1> mov [ebx+4], eax ; superblock address on disk 14417 <1> 14418 <1> ;call diskio 14419 <1> ;retn 14420 <1> ; 28/11/2021 14421 <1> ;jmp diskio 14422 <1> 14423 <1> ; 21/03/2022 14424 0000300C E8BF2A0000 <1> call diskio 14425 00003011 72DA <1> jc short rdi_err 14426 <1> 14427 <1> ; 21/03/2022 14428 <1> ; Note: If superblock is defective or SB sector 14429 <1> ; address is wrong, "ERROR: /etc/init !?" 14430 <1> ; message will appear after here. 14431 <1> ; ..because /etc/init inode will not be found.. 14432 <1> ; So, i am not writing SB validation 14433 <1> ; (check) code here. 14434 <1> ; 14435 <1> ; ((Also, if we are here, everything should be normal!)) 14436 <1> 14437 00003013 C3 <1> retn 14438 <1> 14439 <1> disk_read_err_msg: 14440 <1> ; 21/03/2022 - Retro UNIX 386 v1.2 14441 00003014 070D0A <1> db 07h, 0Dh, 0Ah 14442 00003017 4469736B2072656164- <1> db "Disk read error ! " 14443 00003020 206572726F72202120 <1> 14444 00003029 0D0A00 <1> db 0Dh, 0Ah, 0 14445 <1> 14446 <1> ; 21/03/2022 - Retro UNIX 386 v1.2 14447 <1> runix_p_bs: 14448 <1> ; get retro unix v2 partition's boot sector address 14449 <1> 14450 <1> ; 09/05/2021 14451 <1> ; 19/04/2021 - Retro UNIX 386 v2 14452 <1> ; INPUT: 14453 <1> ; ;;Masterboot buffer at offset mbrbuf 14454 <1> ; ; 21/03/2022 14455 <1> ; esi = Masterboot buffer (data) address 14456 <1> ; OUTPUT: 14457 <1> ; ;;esi = start sector addr of retro unix v2 fs 14458 <1> ; ; 21/03/2022 14459 <1> ; eax = start sector address of retro unix v2 fs 14460 <1> ; 14461 <1> ; cf = 1 -> error, retro unix fs not found 14462 <1> ; (eax = 0) 14463 <1> ; 14464 <1> ; Modified registers: esi, eax 14465 <1> 14466 <1> ptBootable equ 0 14467 <1> ptBeginHead equ 1 14468 <1> ptBeginSector equ 2 14469 <1> ptBeginCylinder equ 3 14470 <1> ptFileSystemID equ 4 14471 <1> ptEndHead equ 5 14472 <1> ptEndSector equ 6 14473 <1> ptEndCylinder equ 7 14474 <1> ptStartSector equ 8 14475 <1> ptSectors equ 12 14476 <1> 14477 <1> FS_RETROUNIX equ 71h ; runix v2 partition ID 14478 <1> 14479 <1> ;cmp word [mbrbuf+510], 0AA55h 14480 0000302C 6681BEFE01000055AA <1> cmp word [esi+510], 0AA55h 14481 00003035 7515 <1> jne short runix_p_nf 14482 <1> 14483 <1> ; partition table entries are at offset 1BEh 14484 <1> ;mov esi, mbrbuf+1BEh+ptFileSystemID 14485 00003037 81C6C2010000 <1> add esi, 1BEh+ptFileSystemID 14486 0000303D 8D4640 <1> lea eax, [esi+(4*16)] 14487 <1> runix_p_bs_0: 14488 00003040 803E71 <1> cmp byte [esi], FS_RETROUNIX ; 71h 14489 00003043 740B <1> je short runix_p_f ; it is retro unix partition 14490 00003045 83C610 <1> add esi, 16 14491 <1> ;cmp esi, mbrbuf+1BEh+ptFileSystemID+(4*16) 14492 00003048 39C6 <1> cmp esi, eax 14493 0000304A 72F4 <1> jb short runix_p_bs_0 14494 <1> runix_p_nf: 14495 0000304C 29C0 <1> sub eax, eax 14496 <1> ; eax = 0 14497 0000304E F9 <1> stc 14498 0000304F C3 <1> retn 14499 <1> runix_p_f: 14500 <1> ;mov esi, [esi+ptStartSector-ptFileSystemID] 14501 00003050 8B4604 <1> mov eax, [esi+ptStartSector-ptFileSystemID] 14502 00003053 C3 <1> retn 14503 <1> 14504 <1> ; 23/10/2015 14505 <1> com1_irq4: 14506 00003054 [5C300000] <1> dd dummy_retn 14507 <1> com2_irq3: 14508 00003058 [5C300000] <1> dd dummy_retn 14509 <1> 14510 <1> dummy_retn: 14511 0000305C C3 <1> retn 14512 %include 'u1.s' ; 10/05/2015 14513 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 14514 <1> ; (re-write kernel for test by using previous version without a major defect) 14515 <1> ; **************************************************************************** 14516 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC 14517 <1> ; Last Modification: 27/12/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.4) 14518 <1> ; ---------------------------------------------------------------------------- 14519 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 14520 <1> ; (v0.1 - Beginning: 11/07/2012) 14521 <1> ; 14522 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 14523 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 14524 <1> ; 14525 <1> ; 14526 <1> ; 14527 <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s 14528 <1> ; 14529 <1> ; **************************************************************************** 14530 <1> 14531 <1> unkni: ; / used for all system calls 14532 <1> sysent: ; < enter to system call > 14533 <1> ; 27/12/2022 14534 <1> ; 25/12/2021 (Retro UNIX 386 v1.2) 14535 <1> ; 19/10/2015 14536 <1> ; 21/09/2015 14537 <1> ; 01/07/2015 14538 <1> ; 19/05/2015 14539 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14540 <1> ; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1) 14541 <1> ; 14542 <1> ; 'unkni' or 'sysent' is sytem entry from various traps. 14543 <1> ; The trap type is determined and an indirect jump is made to 14544 <1> ; the appropriate system call handler. If there is a trap inside 14545 <1> ; the system a jump to panic is made. All user registers are saved 14546 <1> ; and u.sp points to the end of the users stack. The sys (trap) 14547 <1> ; instructor is decoded to get the the system code part (see 14548 <1> ; trap instruction in the PDP-11 handbook) and from this 14549 <1> ; the indirect jump address is calculated. If a bad system call is 14550 <1> ; made, i.e., the limits of the jump table are exceeded, 'badsys' 14551 <1> ; is called. If the call is legitimate control passes to the 14552 <1> ; appropriate system routine. 14553 <1> ; 14554 <1> ; Calling sequence: 14555 <1> ; Through a trap caused by any sys call outside the system. 14556 <1> ; Arguments: 14557 <1> ; Arguments of particular system call. 14558 <1> ; ............................................................... 14559 <1> ; 14560 <1> ; Retro UNIX 8086 v1 modification: 14561 <1> ; System call number is in EAX register. 14562 <1> ; 14563 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 14564 <1> ; registers depending of function details. 14565 <1> ; 14566 <1> ; 16/04/2015 14567 0000305D 368925[9C6C0000] <1> mov [ss:u.sp], esp ; Kernel stack points to return address 14568 <1> ; save user registers 14569 00003064 1E <1> push ds 14570 00003065 06 <1> push es 14571 00003066 0FA0 <1> push fs 14572 00003068 0FA8 <1> push gs 14573 0000306A 60 <1> pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 14574 <1> ; 14575 <1> ; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015 14576 <1> ; (ESPACE is size of space in kernel stack 14577 <1> ; for saving/restoring user registers.) 14578 <1> ; 14579 0000306B 50 <1> push eax ; 01/07/2015 14580 0000306C 66B81000 <1> mov ax, KDATA 14581 00003070 8ED8 <1> mov ds, ax 14582 00003072 8EC0 <1> mov es, ax 14583 00003074 8EE0 <1> mov fs, ax 14584 00003076 8EE8 <1> mov gs, ax 14585 00003078 A1[68670000] <1> mov eax, [k_page_dir] 14586 0000307D 0F22D8 <1> mov cr3, eax 14587 00003080 58 <1> pop eax ; 01/07/2015 14588 <1> ; 19/10/2015 14589 00003081 FC <1> cld 14590 <1> ; 14591 00003082 FE05[986C0000] <1> inc byte [sysflg] 14592 <1> ; incb sysflg / indicate a system routine is in progress 14593 00003088 FB <1> sti ; 18/01/2014 14594 <1> ;jnz panic ; 24/05/2013 14595 <1> ; 04/12/2021 14596 00003089 7405 <1> jz short _1 14597 0000308B E91BF9FFFF <1> jmp panic 14598 <1> ; beq 1f 14599 <1> ; jmp panic ; / called if trap inside system 14600 <1> ;1: 14601 <1> _1: ; 04/12/2021 14602 <1> ; 16/04/2015 14603 00003090 A3[A46C0000] <1> mov [u.r0], eax 14604 00003095 8925[A06C0000] <1> mov [u.usp], esp ; kernel stack points to user's registers 14605 <1> ; 14606 <1> ; mov $s.syst+2,clockp 14607 <1> ; mov r0,-(sp) / save user registers 14608 <1> ; mov sp,u.r0 / pointer to bottom of users stack 14609 <1> ; / in u.r0 14610 <1> ; mov r1,-(sp) 14611 <1> ; mov r2,-(sp) 14612 <1> ; mov r3,-(sp) 14613 <1> ; mov r4,-(sp) 14614 <1> ; mov r5,-(sp) 14615 <1> ; mov ac,-(sp) / "accumulator" register for extended 14616 <1> ; / arithmetic unit 14617 <1> ; mov mq,-(sp) / "multiplier quotient" register for the 14618 <1> ; / extended arithmetic unit 14619 <1> ; mov sc,-(sp) / "step count" register for the extended 14620 <1> ; / arithmetic unit 14621 <1> ; mov sp,u.sp / u.sp points to top of users stack 14622 <1> ; mov 18.(sp),r0 / store pc in r0 14623 <1> ; mov -(r0),r0 / sys inst in r0 10400xxx 14624 <1> ; sub $sys,r0 / get xxx code 14625 0000309B C1E002 <1> shl eax, 2 14626 <1> ; asl r0 / multiply by 2 to jump indirect in bytes 14627 0000309E 3DA4000000 <1> cmp eax, end_of_syscalls - syscalls 14628 <1> ; cmp r0,$2f-1f / limit of table (35) exceeded 14629 <1> ;jnb short badsys 14630 <1> ; bhis badsys / yes, bad system call 14631 <1> ; 25/12/2021 14632 000030A3 7205 <1> jb short _2 14633 000030A5 E96D010000 <1> jmp badsys 14634 <1> _2: 14635 <1> ; 25/12/2021 14636 <1> ;cmc 14637 <1> ;pushf 14638 <1> ;push eax 14639 000030AA 8B2D[9C6C0000] <1> mov ebp, [u.sp] ; Kernel stack at the beginning of sys call 14640 <1> ;mov al, 0FEh ; 11111110b 14641 <1> ;;adc al, 0 ; al = al + cf 14642 <1> ;and [ebp+8], al ; flags (reset carry flag) 14643 000030B0 806508FE <1> and byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021 14644 <1> ; bic $341,20.(sp) / set users processor priority to 0 14645 <1> ; / and clear carry bit 14646 <1> ;pop ebp ; eax 14647 000030B4 89C5 <1> mov ebp, eax ; 25/12/2021 14648 <1> ;popf 14649 <1> ;;jc badsys 14650 <1> ;; 04/12/2021 14651 <1> ;jnc short _3 14652 <1> ;jmp badsys 14653 <1> ;_3: 14654 000030B6 A1[A46C0000] <1> mov eax, [u.r0] 14655 <1> ; system call registers: EAX, EDX, ECX, EBX, ESI, EDI 14656 000030BB FFA5[C1300000] <1> jmp dword [ebp+syscalls] 14657 <1> ; jmp *1f(r0) / jump indirect thru table of addresses 14658 <1> ; / to proper system routine. 14659 <1> 14660 <1> ; 27/12/2022 (sysmemory) 14661 <1> ; 09/01/2022 14662 <1> ; 01/01/2022 (/etc/init error, BugFix efforts, test) 14663 <1> syscalls: ; 1: 14664 <1> ; 21/09/2015 14665 <1> ; 01/07/2015 14666 <1> ; 16/04/2015 (32 bit address modification) 14667 000030C1 [E1310000] <1> dd sysrele ; / 0 14668 000030C5 [89320000] <1> dd sysexit ; / 1 14669 000030C9 [B3330000] <1> dd sysfork ; / 2 14670 000030CD [B8340000] <1> dd sysread ; / 3 14671 000030D1 [CD340000] <1> dd syswrite ; / 4 14672 000030D5 [30350000] <1> dd sysopen ; / 5 14673 000030D9 [59360000] <1> dd sysclose ; / 6 14674 000030DD [2E330000] <1> dd syswait ; / 7 14675 000030E1 [C1350000] <1> dd syscreat ; / 8 14676 000030E5 [0F3A0000] <1> dd syslink ; / 9 14677 000030E9 [9D3A0000] <1> dd sysunlink ; / 10 14678 000030ED [BD3B0000] <1> dd sysexec ; / 11 14679 000030F1 [2A420000] <1> dd syschdir ; / 12 14680 000030F5 [2C430000] <1> dd systime ; / 13 14681 000030F9 [08360000] <1> dd sysmkdir ; / 14 14682 000030FD [69420000] <1> dd syschmod ; / 15 14683 00003101 [98420000] <1> dd syschown ; / 16 14684 00003105 [60430000] <1> dd sysbreak ; / 17 14685 00003109 [603F0000] <1> dd sysstat ; / 18 14686 0000310D [6E440000] <1> dd sysseek ; / 19 14687 00003111 [80440000] <1> dd systell ; / 20 14688 00003115 [2E540000] <1> dd sysmount ; / 21 14689 00003119 [47550000] <1> dd sysumount ; / 22 14690 0000311D [F1440000] <1> dd syssetuid ; / 23 14691 00003121 [26450000] <1> dd sysgetuid ; / 24 14692 00003125 [3B430000] <1> dd sysstime ; / 25 14693 00003129 [E5440000] <1> dd sysquit ; / 26 14694 0000312D [D9440000] <1> dd sysintr ; / 27 14695 00003131 [473F0000] <1> dd sysfstat ; / 28 14696 00003135 [74360000] <1> dd sysemt ; / 29 14697 00003139 [C2360000] <1> dd sysmdate ; / 30 14698 0000313D [1F370000] <1> dd sysstty ; / 31 14699 00003141 [09390000] <1> dd sysgtty ; / 32 14700 00003145 [BD360000] <1> dd sysilgins ; / 33 14701 00003149 [FA5C0000] <1> dd syssleep ; 34 ; Retro UNIX 8086 v1 feature only ! 14702 <1> ; 11/06/2014 14703 0000314D [275D0000] <1> dd sysmsg ; 35 ; Retro UNIX 386 v1 feature only ! 14704 <1> ; 01/07/2015 14705 00003151 [FF5D0000] <1> dd sysgeterr ; 36 ; Retro UNIX 386 v1 feature only ! 14706 <1> ; 21/09/2015 - get last error number 14707 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 14708 <1> ; 27/03/2021 - Retro UNIX 386 v2 14709 00003155 [3F450000] <1> dd syssetgid ; 37 14710 00003159 [62450000] <1> dd sysgetgid ; 38 14711 <1> ; 18/06/2021 - Retro UNIX 386 v2 (ref: TRDOS 386 v2) 14712 0000315D [77450000] <1> dd sysver ; 39 ; (get) Retro Unix 386 version 14713 <1> ; 27/12/2022 - Retro UNIX 386 v1.2 14714 00003161 [265E0000] <1> dd sysmemory ; 40 ; get available (total&free) memory 14715 <1> 14716 <1> end_of_syscalls: 14717 <1> 14718 <1> error: 14719 <1> ; 11/12/2021 (Retro UNIX 386 v1.2) 14720 <1> ; 17/09/2015 14721 <1> ; 03/09/2015 14722 <1> ; 01/09/2015 14723 <1> ; 09/06/2015 14724 <1> ; 13/05/2015 14725 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14726 <1> ; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 14727 <1> ; 14728 <1> ; 'error' merely sets the error bit off the processor status (c-bit) 14729 <1> ; then falls right into the 'sysret', 'sysrele' return sequence. 14730 <1> ; 14731 <1> ; INPUTS -> none 14732 <1> ; OUTPUTS -> 14733 <1> ; processor status - carry (c) bit is set (means error) 14734 <1> ; 14735 <1> ; 26/05/2013 (Stack pointer must be reset here! 14736 <1> ; Because, jumps to error procedure 14737 <1> ; disrupts push-pop nesting balance) 14738 <1> ; 14739 00003165 8B2D[9C6C0000] <1> mov ebp, [u.sp] ; interrupt (system call) return (iretd) address 14740 0000316B 804D0801 <1> or byte [ebp+8], 1 ; set carry bit of flags register 14741 <1> ; (system call will return with cf = 1) 14742 <1> ; bis $1,20.(r1) / set c bit in processor status word below 14743 <1> ; / users stack 14744 <1> ; 17/09/2015 14745 0000316F 83ED30 <1> sub ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc') 14746 <1> ; for saving/restoring user registers 14747 <1> ;cmp ebp, [u.usp] 14748 <1> ;je short err0 14749 00003172 892D[A06C0000] <1> mov [u.usp], ebp 14750 <1> ;err0: 14751 <1> ; 01/09/2015 14752 00003178 8B25[A06C0000] <1> mov esp, [u.usp] ; Retro Unix 8086 v1 modification! 14753 <1> ; 10/04/2013 14754 <1> ; (If an I/O error occurs during disk I/O, 14755 <1> ; related procedures will jump to 'error' 14756 <1> ; procedure directly without returning to 14757 <1> ; the caller procedure. So, stack pointer 14758 <1> ; must be restored here.) 14759 <1> ; 13/05/2015 14760 <1> ; NOTE: (The last) error code is in 'u.error', it can be retrieved by 14761 <1> ; 'get last error' system call later. 14762 <1> 14763 <1> ; 03/09/2015 - 09/06/2015 - 07/08/2013 14764 0000317E C605[166D0000]00 <1> mov byte [u.kcall], 0 ; namei_r, mkdir_w reset 14765 <1> 14766 <1> sysret: ; < return from system call> 14767 <1> ; 11/12/2021 14768 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 14769 <1> ; 30/11/2021 14770 <1> ; 10/09/2015 14771 <1> ; 29/07/2015 14772 <1> ; 25/06/2015 14773 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14774 <1> ; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 14775 <1> ; 14776 <1> ; 'sysret' first checks to see if process is about to be 14777 <1> ; terminated (u.bsys). If it is, 'sysexit' is called. 14778 <1> ; If not, following happens: 14779 <1> ; 1) The user's stack pointer is restored. 14780 <1> ; 2) r1=0 and 'iget' is called to see if last mentioned 14781 <1> ; i-node has been modified. If it has, it is written out 14782 <1> ; via 'ppoke'. 14783 <1> ; 3) If the super block has been modified, it is written out 14784 <1> ; via 'ppoke'. 14785 <1> ; 4) If the dismountable file system's super block has been 14786 <1> ; modified, it is written out to the specified device 14787 <1> ; via 'ppoke'. 14788 <1> ; 5) A check is made if user's time quantum (uquant) ran out 14789 <1> ; during his execution. If so, 'tswap' is called to give 14790 <1> ; another user a chance to run. 14791 <1> ; 6) 'sysret' now goes into 'sysrele'. 14792 <1> ; (See 'sysrele' for conclusion.) 14793 <1> ; 14794 <1> ; Calling sequence: 14795 <1> ; jump table or 'br sysret' 14796 <1> ; Arguments: 14797 <1> ; - 14798 <1> ; ............................................................... 14799 <1> ; 14800 <1> ; ((AX=r1 for 'iget' input)) 14801 <1> ; 14802 <1> ;xor ax, ax ; 04/05/2013 14803 <1> ; 30/11/2021 14804 00003185 31C0 <1> xor eax, eax 14805 <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec) 14806 00003187 FEC0 <1> inc al ; 04/05/2013 14807 00003189 3805[F46C0000] <1> cmp [u.bsys], al ; 1 14808 <1> ; tstb u.bsys / is a process about to be terminated because 14809 <1> ;jnb sysexit ; 04/05/2013 14810 <1> ; ; bne sysexit / of an error? yes, go to sysexit 14811 <1> ; 04/12/2021 14812 0000318F 720F <1> jb short _3 14813 <1> ; 11/12/2021 14814 00003191 C705[186D0000]0100- <1> mov dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !' 14815 00003199 0000 <1> 14816 0000319B E9E9000000 <1> jmp sysexit 14817 <1> _3: 14818 <1> ;mov esp, [u.usp] ; 24/05/2013 (that is not needed here) 14819 <1> ; mov u.sp,sp / no point stack to users stack 14820 000031A0 FEC8 <1> dec al ; mov ax, 0 14821 <1> ; clr r1 / zero r1 to check last mentioned i-node 14822 000031A2 E8CE190000 <1> call iget 14823 <1> ; jsr r0,iget / if last mentioned i-node has been modified 14824 <1> ; / it is written out 14825 <1> ;xor ax, ax ; 0 14826 <1> ; 30/11/2021 14827 000031A7 31C0 <1> xor eax, eax 14828 000031A9 3805[966C0000] <1> cmp [smod], al ; 0 14829 <1> ; tstb smod / has the super block been modified 14830 000031AF 7614 <1> jna short sysret1 14831 <1> ; beq 1f / no, 1f 14832 000031B1 A2[966C0000] <1> mov [smod], al ; 0 14833 <1> ; clrb smod / yes, clear smod 14834 000031B6 BB[4C6D0000] <1> mov ebx, sb0 ;; 07/08//2013 14835 000031BB 66810B0002 <1> or word [ebx], 200h ;; 14836 <1> ;or word [sb0], 200h ; write bit, bit 9 14837 <1> ; bis $1000,sb0 / set write bit in I/O queue for super block 14838 <1> ; / output 14839 <1> ; AX = 0 14840 000031C0 E86F280000 <1> call poke ; 07/08/2013 14841 <1> ;call ppoke 14842 <1> ; AX = 0 14843 <1> ; jsr r0,ppoke / write out modified super block to disk 14844 <1> sysret1: ;1: 14845 000031C5 3805[976C0000] <1> cmp [mmod], al ; 0 14846 <1> ; tstb mmod / has the super block for the dismountable file 14847 <1> ; / system 14848 000031CB 7614 <1> jna short sysrel0 14849 <1> ; beq 1f / been modified? no, 1f 14850 000031CD A2[976C0000] <1> mov [mmod], al ; 0 14851 <1> ; clrb mmod / yes, clear mmod 14852 <1> ;mov ax, [mntd] 14853 <1> ;;mov al, [mdev] ; 26/04/2013 14854 000031D2 BB[546F0000] <1> mov ebx, sb1 ;; 07/08//2013 14855 <1> ;;mov [ebx], al 14856 <1> ;mov [sb1], al 14857 <1> ; movb mntd,sb1 / set the I/O queue 14858 000031D7 66810B0002 <1> or word [ebx], 200h 14859 <1> ;or word [sb1], 200h ; write bit, bit 9 14860 <1> ; bis $1000,sb1 / set write bit in I/O queue for detached sb 14861 000031DC E853280000 <1> call poke ; 07/08/2013 14862 <1> ;call ppoke 14863 <1> ; jsr r0,ppoke / write it out to its device 14864 <1> ;xor al, al ; 26/04/2013 14865 <1> ;1: 14866 <1> ; tstb uquant / is the time quantum 0? 14867 <1> ; bne 1f / no, don't swap it out 14868 <1> 14869 <1> sysrele: ; < release > 14870 <1> ; 14/10/2015 14871 <1> ; 01/09/2015 14872 <1> ; 24/07/2015 14873 <1> ; 14/05/2015 14874 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14875 <1> ; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1) 14876 <1> ; 14877 <1> ; 'sysrele' first calls 'tswap' if the time quantum for a user is 14878 <1> ; zero (see 'sysret'). It then restores the user's registers and 14879 <1> ; turns off the system flag. It then checked to see if there is 14880 <1> ; an interrupt from the user by calling 'isintr'. If there is, 14881 <1> ; the output gets flashed (see isintr) and interrupt action is 14882 <1> ; taken by a branch to 'intract'. If there is no interrupt from 14883 <1> ; the user, a rti is made. 14884 <1> ; 14885 <1> ; Calling sequence: 14886 <1> ; Fall through a 'bne' in 'sysret' & ? 14887 <1> ; Arguments: 14888 <1> ; - 14889 <1> ; ............................................................... 14890 <1> ; 14891 <1> ; 23/02/2014 (swapret) 14892 <1> ; 22/09/2013 14893 <1> sysrel0: ;1: 14894 000031E1 803D[EC6C0000]00 <1> cmp byte [u.quant], 0 ; 16/05/2013 14895 <1> ; tstb uquant / is the time quantum 0? 14896 000031E8 7705 <1> ja short swapret 14897 <1> ; bne 1f / no, don't swap it out 14898 <1> sysrelease: ; 07/12/2013 (jump from 'clock') 14899 000031EA E808140000 <1> call tswap 14900 <1> ; jsr r0,tswap / yes, swap it out 14901 <1> ; 14902 <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address. 14903 <1> swapret: ;1: 14904 <1> ; 10/09/2015 14905 <1> ; 01/09/2015 14906 <1> ; 14/05/2015 14907 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications) 14908 <1> ; 26/05/2013 (Retro UNIX 8086 v1) 14909 <1> ; cli 14910 <1> ; 24/07/2015 14911 <1> ; 14912 <1> ;; 'esp' must be already equal to '[u.usp]' here ! 14913 <1> ;; mov esp, [u.usp] 14914 <1> 14915 <1> ; 22/09/2013 14916 000031EF E8DA150000 <1> call isintr 14917 <1> ; 20/10/2013 14918 000031F4 7405 <1> jz short sysrel1 14919 000031F6 E877000000 <1> call intract 14920 <1> ; jsr r0,isintr / is there an interrupt from the user 14921 <1> ; br intract / yes, output gets flushed, take interrupt 14922 <1> ; / action 14923 <1> sysrel1: 14924 000031FB FA <1> cli ; 14/10/2015 14925 000031FC FE0D[986C0000] <1> dec byte [sysflg] 14926 <1> ; decb sysflg / turn system flag off 14927 00003202 A1[046D0000] <1> mov eax, [u.pgdir] 14928 00003207 0F22D8 <1> mov cr3, eax ; 1st PDE points to Kernel Page Table 0 (1st 4 MB) 14929 <1> ; (others are different than kernel page tables) 14930 <1> ; 10/09/2015 14931 0000320A 61 <1> popad ; edi, esi, ebp, temp (increment esp by 4), ebx, edx, ecx, eax 14932 <1> ; mov (sp)+,sc / restore user registers 14933 <1> ; mov (sp)+,mq 14934 <1> ; mov (sp)+,ac 14935 <1> ; mov (sp)+,r5 14936 <1> ; mov (sp)+,r4 14937 <1> ; mov (sp)+,r3 14938 <1> ; mov (sp)+,r2 14939 <1> ; 14940 0000320B A1[A46C0000] <1> mov eax, [u.r0] ; ((return value in EAX)) 14941 00003210 0FA9 <1> pop gs 14942 00003212 0FA1 <1> pop fs 14943 00003214 07 <1> pop es 14944 00003215 1F <1> pop ds 14945 00003216 CF <1> iretd 14946 <1> ; rti / no, return from interrupt 14947 <1> 14948 <1> badsys: 14949 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14950 <1> ; (Major Modification: 'core' dumping procedure in 14951 <1> ; original UNIX v1 and Retro UNIX 8086 v1 14952 <1> ; has been changed to print 'Invalid System Call !' 14953 <1> ; message on the user's console tty.) 14954 <1> ; (EIP, EAX values will be shown on screen with error message) 14955 <1> ; (EIP = Return address just after the system call -INT 30h-) 14956 <1> ; (EAX = Function number) 14957 <1> ; 14958 00003217 FE05[F46C0000] <1> inc byte [u.bsys] 14959 <1> ; 14960 0000321D 8B1D[9C6C0000] <1> mov ebx, [u.sp] ; esp at the beginning of 'sysent' 14961 00003223 8B03 <1> mov eax, [ebx] ; EIP (return address, not 'INT 30h' address) 14962 00003225 E8B8E3FFFF <1> call dwordtohex 14963 0000322A 8915[C8640000] <1> mov [bsys_msg_eip], edx 14964 00003230 A3[CC640000] <1> mov [bsys_msg_eip+4], eax 14965 00003235 A1[A46C0000] <1> mov eax, [u.r0] 14966 0000323A E8A3E3FFFF <1> call dwordtohex 14967 0000323F 8915[B8640000] <1> mov [bsys_msg_eax], edx 14968 00003245 A3[BC640000] <1> mov [bsys_msg_eax+4], eax 14969 <1> ; 11/12/2021 14970 <1> ;xor eax, eax 14971 <1> ;mov dword [u.base], badsys_msg ; "Invalid System Call !" 14972 <1> ;mov ebx, [u.fofp] 14973 <1> ;mov [ebx], eax 14974 <1> ;;mov eax, 1 ; inode number of console tty (for user) 14975 <1> ;inc eax 14976 <1> ; 11/12/2021 - Retro UNIX 386 v2 fs compatibility 14977 <1> ; (Retro UNIX 386 v1.2) 14978 <1> ;mov al, 8 ; /dev/tty inode number (runix v2 fs) 14979 <1> ;; eax = 8 ; inode number of console tty (for user) 14980 <1> ;mov dword [u.count], BSYS_M_SIZE 14981 <1> ; writei 14982 <1> ; INPUTS -> 14983 <1> ; r1 - inode number 14984 <1> ; u.count - byte count to be written 14985 <1> ; u.base - points to user buffer 14986 <1> ; u.fofp - points to word with current file offset 14987 <1> ; OUTPUTS -> 14988 <1> ; u.count - cleared 14989 <1> ; u.nread - accumulates total bytes passed back 14990 <1> ; 14991 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 14992 <1> ;call writei 14993 <1> ;;mov eax, 1 14994 <1> ;jmp sysexit 14995 <1> 14996 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 14997 0000324A BE[99640000] <1> mov esi, badsys_msg ; "Invalid System Call !" 14998 0000324F 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 14999 00003256 8A83[A3680000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 15000 0000325C C605[97670000]0F <1> mov byte [ccolor], 0Fh ; white (message) color 15001 00003263 A2[D96C0000] <1> mov [u.ttyn], al ; current (active) tty (for user) 15002 00003268 E8772B0000 <1> call print_cmsg 15003 <1> ;mov dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !' 15004 0000326D E9F3FEFFFF <1> jmp error 15005 <1> 15006 <1> ; incb u.bsys / turn on the user's bad-system flag 15007 <1> ; mov $3f,u.namep / point u.namep to "core\0\0" 15008 <1> ; jsr r0,namei / get the i-number for the core image file 15009 <1> ; br 1f / error 15010 <1> ; neg r1 / negate the i-number to open the core image file 15011 <1> ; / for writing 15012 <1> ; jsr r0,iopen / open the core image file 15013 <1> ; jsr r0,itrunc / free all associated blocks 15014 <1> ; br 2f 15015 <1> ;1: 15016 <1> ; mov $17,r1 / put i-node mode (17) in r1 15017 <1> ; jsr r0,maknod / make an i-node 15018 <1> ; mov u.dirbuf,r1 / put i-node number in r1 15019 <1> ;2: 15020 <1> ; mov $core,u.base / move address core to u.base 15021 <1> ; mov $ecore-core,u.count / put the byte count in u.count 15022 <1> ; mov $u.off,u.fofp / more user offset to u.fofp 15023 <1> ; clr u.off / clear user offset 15024 <1> ; jsr r0,writei / write out the core image to the user 15025 <1> ; mov $user,u.base / pt. u.base to user 15026 <1> ; mov $64.,u.count / u.count = 64 15027 <1> ; jsr r0,writei / write out all the user parameters 15028 <1> ; neg r1 / make i-number positive 15029 <1> ; jsr r0,iclose / close the core image file 15030 <1> ; br sysexit / 15031 <1> ;3: 15032 <1> ; 15033 <1> 15034 <1> intract: ; / interrupt action 15035 <1> ; 14/10/2015 15036 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 15037 <1> ; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1) 15038 <1> ; 15039 <1> ; Retro UNIX 8086 v1 modification ! 15040 <1> ; (Process/task switching and quit routine by using 15041 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 15042 <1> ; 15043 <1> ; input -> 'u.quit' (also value of 'u.intr' > 0) 15044 <1> ; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign) 15045 <1> ; 'intract' will jump to 'sysexit'. 15046 <1> ; Intract will return to the caller 15047 <1> ; if value of 'u.quit' <> FFFFh. 15048 <1> ; 14/10/2015 15049 00003272 FB <1> sti 15050 <1> ; 07/12/2013 15051 00003273 66FF05[F26C0000] <1> inc word [u.quit] 15052 0000327A 7408 <1> jz short intrct0 ; FFFFh -> 0 15053 0000327C 66FF0D[F26C0000] <1> dec word [u.quit] 15054 <1> ; 16/04/2015 15055 00003283 C3 <1> retn 15056 <1> intrct0: 15057 00003284 58 <1> pop eax ; call intract -> retn 15058 <1> ; 15059 00003285 31C0 <1> xor eax, eax 15060 00003287 FEC0 <1> inc al ; mov ax, 1 15061 <1> ;;; 15062 <1> ; UNIX v1 original 'intract' routine... 15063 <1> ; / interrupt action 15064 <1> ;cmp *(sp),$rti / are you in a clock interrupt? 15065 <1> ; bne 1f / no, 1f 15066 <1> ; cmp (sp)+,(sp)+ / pop clock pointer 15067 <1> ; 1: / now in user area 15068 <1> ; mov r1,-(sp) / save r1 15069 <1> ; mov u.ttyp,r1 15070 <1> ; / pointer to tty buffer in control-to r1 15071 <1> ; cmpb 6(r1),$177 15072 <1> ; / is the interrupt char equal to "del" 15073 <1> ; beq 1f / yes, 1f 15074 <1> ; clrb 6(r1) 15075 <1> ; / no, clear the byte 15076 <1> ; / (must be a quit character) 15077 <1> ; mov (sp)+,r1 / restore r1 15078 <1> ; clr u.quit / clear quit flag 15079 <1> ; bis $20,2(sp) 15080 <1> ; / set trace for quit (sets t bit of 15081 <1> ; / ps-trace trap) 15082 <1> ; rti ; / return from interrupt 15083 <1> ; 1: / interrupt char = del 15084 <1> ; clrb 6(r1) / clear the interrupt byte 15085 <1> ; / in the buffer 15086 <1> ; mov (sp)+,r1 / restore r1 15087 <1> ; cmp u.intr,$core / should control be 15088 <1> ; / transferred to loc core? 15089 <1> ; blo 1f 15090 <1> ; jmp *u.intr / user to do rti yes, 15091 <1> ; / transfer to loc core 15092 <1> ; 1: 15093 <1> ; sys 1 / exit 15094 <1> 15095 <1> sysexit: ; 15096 <1> ; 17/07/2022 15097 <1> ; 30/11/2021 - Retro UNIX 386 v1.2 15098 <1> ; 01/09/2015 15099 <1> ; 31/08/2015 15100 <1> ; 14/05/2015 15101 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 15102 <1> ; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 15103 <1> ; 15104 <1> ; 'sysexit' terminates a process. First each file that 15105 <1> ; the process has opened is closed by 'flose'. The process 15106 <1> ; status is then set to unused. The 'p.pid' table is then 15107 <1> ; searched to find children of the dying process. If any of 15108 <1> ; children are zombies (died by not waited for), they are 15109 <1> ; set free. The 'p.pid' table is then searched to find the 15110 <1> ; dying process's parent. When the parent is found, it is 15111 <1> ; checked to see if it is free or it is a zombie. If it is 15112 <1> ; one of these, the dying process just dies. If it is waiting 15113 <1> ; for a child process to die, it notified that it doesn't 15114 <1> ; have to wait anymore by setting it's status from 2 to 1 15115 <1> ; (waiting to active). It is awakened and put on runq by 15116 <1> ; 'putlu'. The dying process enters a zombie state in which 15117 <1> ; it will never be run again but stays around until a 'wait' 15118 <1> ; is completed by it's parent process. If the parent is not 15119 <1> ; found, process just dies. This means 'swap' is called with 15120 <1> ; 'u.uno=0'. What this does is the 'wswap' is not called 15121 <1> ; to write out the process and 'rswap' reads the new process 15122 <1> ; over the one that dies..i.e., the dying process is 15123 <1> ; overwritten and destroyed. 15124 <1> ; 15125 <1> ; Calling sequence: 15126 <1> ; sysexit or conditional branch. 15127 <1> ; Arguments: 15128 <1> ; - 15129 <1> ; ............................................................... 15130 <1> ; 15131 <1> ; Retro UNIX 8086 v1 modification: 15132 <1> ; System call number (=1) is in EAX register. 15133 <1> ; 15134 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 15135 <1> ; registers depending of function details. 15136 <1> ; 15137 <1> ; ('swap' procedure is mostly different than original UNIX v1.) 15138 <1> ; 15139 <1> ; / terminate process 15140 <1> ; AX = 1 15141 <1> ;dec ax ; 0 15142 <1> ; 30/11/2021 15143 00003289 48 <1> dec eax ; 0 15144 0000328A 66A3[F06C0000] <1> mov [u.intr], ax ; 0 15145 <1> ; clr u.intr / clear interrupt control word 15146 <1> ; clr r1 / clear r1 15147 <1> ; AX = 0 15148 <1> sysexit_1: ; 1: 15149 <1> ; AX = File descriptor 15150 <1> ; / r1 has file descriptor (index to u.fp list) 15151 <1> ; / Search the whole list 15152 00003290 E8690D0000 <1> call fclose 15153 <1> ; jsr r0,fclose / close all files the process opened 15154 <1> ;; ignore error return 15155 <1> ; br .+2 / ignore error return 15156 <1> ;inc ax 15157 00003295 FEC0 <1> inc al 15158 <1> ; inc r1 / increment file descriptor 15159 <1> ;cmp ax, 10 15160 00003297 3C0A <1> cmp al, 10 15161 <1> ; cmp r1,$10. / end of u.fp list? 15162 00003299 72F5 <1> jb short sysexit_1 15163 <1> ; blt 1b / no, go back 15164 0000329B 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 15165 <1> ; movb u.uno,r1 / yes, move dying process's number to r1 15166 000032A2 88A3[C3680000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 15167 <1> ; clrb p.stat-1(r1) / free the process 15168 <1> ;shl bx, 1 15169 000032A8 D0E3 <1> shl bl, 1 15170 <1> ; asl r1 / use r1 for index into the below tables 15171 000032AA 668B8B[62680000] <1> mov cx, [ebx+p.pid-2] 15172 <1> ; mov p.pid-2(r1),r3 / move dying process's name to r3 15173 000032B1 668B93[82680000] <1> mov dx, [ebx+p.ppid-2] 15174 <1> ; mov p.ppid-2(r1),r4 / move its parents name to r4 15175 <1> ; xor bx, bx ; 0 15176 000032B8 30DB <1> xor bl, bl ; 0 15177 <1> ; clr r2 15178 000032BA 31F6 <1> xor esi, esi ; 0 15179 <1> ; clr r5 / initialize reg 15180 <1> sysexit_2: ; 1: 15181 <1> ; / find children of this dying process, 15182 <1> ; / if they are zombies, free them 15183 <1> ;add bx, 2 15184 000032BC 80C302 <1> add bl, 2 15185 <1> ; add $2,r2 / search parent process table 15186 <1> ; / for dying process's name 15187 000032BF 66398B[82680000] <1> cmp [ebx+p.ppid-2], cx 15188 <1> ; cmp p.ppid-2(r2),r3 / found it? 15189 000032C6 7513 <1> jne short sysexit_4 15190 <1> ; bne 3f / no 15191 <1> ;shr bx, 1 15192 000032C8 D0EB <1> shr bl, 1 15193 <1> ; asr r2 / yes, it is a parent 15194 000032CA 80BB[C3680000]03 <1> cmp byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 15195 <1> ; cmpb p.stat-1(r2),$3 / is the child of this 15196 <1> ; / dying process a zombie 15197 000032D1 7506 <1> jne short sysexit_3 15198 <1> ; bne 2f / no 15199 000032D3 88A3[C3680000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 15200 <1> ; clrb p.stat-1(r2) / yes, free the child process 15201 <1> sysexit_3: ; 2: 15202 <1> ;shr bx, 1 15203 000032D9 D0E3 <1> shl bl, 1 15204 <1> ; asl r2 15205 <1> sysexit_4: ; 3: 15206 <1> ; / search the process name table 15207 <1> ; / for the dying process's parent 15208 000032DB 663993[62680000] <1> cmp [ebx+p.pid-2], dx ; 17/09/2013 15209 <1> ; cmp p.pid-2(r2),r4 / found it? 15210 000032E2 7502 <1> jne short sysexit_5 15211 <1> ; bne 3f / no 15212 000032E4 89DE <1> mov esi, ebx 15213 <1> ; mov r2,r5 / yes, put index to p.pid table (parents 15214 <1> ; / process # x2) in r5 15215 <1> sysexit_5: ; 3: 15216 <1> ;cmp bx, nproc + nproc 15217 000032E6 80FB20 <1> cmp bl, nproc + nproc 15218 <1> ; cmp r2,$nproc+nproc / has whole table been searched? 15219 000032E9 72D1 <1> jb short sysexit_2 15220 <1> ; blt 1b / no, go back 15221 <1> ; mov r5,r1 / yes, r1 now has parents process # x2 15222 000032EB 21F6 <1> and esi, esi ; r5=r1 15223 000032ED 7430 <1> jz short sysexit_6 15224 <1> ; beq 2f / no parent has been found. 15225 <1> ; / The process just dies 15226 <1> ;shr si, 1 15227 <1> ; 17/07/2022 15228 000032EF D1EE <1> shr esi, 1 15229 <1> ; asr r1 / set up index to p.stat 15230 000032F1 8A86[C3680000] <1> mov al, [esi+p.stat-1] 15231 <1> ; movb p.stat-1(r1),r2 / move status of parent to r2 15232 000032F7 20C0 <1> and al, al 15233 000032F9 7424 <1> jz short sysexit_6 15234 <1> ; beq 2f / if its been freed, 2f 15235 000032FB 3C03 <1> cmp al, 3 15236 <1> ; cmp r2,$3 / is parent a zombie? 15237 000032FD 7420 <1> je short sysexit_6 15238 <1> ; beq 2f / yes, 2f 15239 <1> ; BH = 0 15240 000032FF 8A1D[F56C0000] <1> mov bl, [u.uno] 15241 <1> ; movb u.uno,r3 / move dying process's number to r3 15242 00003305 C683[C3680000]03 <1> mov byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 15243 <1> ; movb $3,p.stat-1(r3) / make the process a zombie 15244 <1> ; 05/02/2014 15245 0000330C 3C01 <1> cmp al, 1 ; SRUN 15246 0000330E 740F <1> je short sysexit_6 15247 <1> ;cmp al, 2 15248 <1> ; cmp r2,$2 / is the parent waiting for 15249 <1> ; / this child to die 15250 <1> ;jne short sysexit_6 15251 <1> ; bne 2f / yes, notify parent not to wait any more 15252 <1> ; 05/02/2014 15253 <1> ; p.stat = 2 --> waiting 15254 <1> ; p.stat = 4 --> sleeping 15255 00003310 C686[C3680000]01 <1> mov byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014 15256 <1> ;dec byte [esi+p.stat-1] 15257 <1> ; decb p.stat-1(r1) / awaken it by putting it (parent) 15258 00003317 6689F0 <1> mov ax, si ; r1 (process number in AL) 15259 <1> ; 15260 <1> ;mov ebx, runq + 4 15261 <1> ; mov $runq+4,r2 / on the runq 15262 0000331A E8AF130000 <1> call putlu 15263 <1> ; jsr r0, putlu 15264 <1> sysexit_6: ; 2: 15265 <1> ; 31/08/2015 15266 <1> ; / the process dies 15267 0000331F C605[F56C0000]00 <1> mov byte [u.uno], 0 15268 <1> ; clrb u.uno / put zero as the process number, 15269 <1> ; / so "swap" will 15270 00003326 E8D6120000 <1> call swap 15271 <1> ; jsr r0,swap / overwrite process with another process 15272 <1> hlt_sys: 15273 <1> ;sti ; 18/01/2014 15274 <1> hlts0: 15275 0000332B F4 <1> hlt 15276 0000332C EBFD <1> jmp short hlts0 15277 <1> ; 0 / and thereby kill it; halt? 15278 <1> 15279 <1> syswait: ; < wait for a processs to die > 15280 <1> ; 09/02/2022 15281 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 15282 <1> ; 17/09/2015 15283 <1> ; 02/09/2015 15284 <1> ; 01/09/2015 15285 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 15286 <1> ; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1) 15287 <1> ; 15288 <1> ; 'syswait' waits for a process die. 15289 <1> ; It works in following way: 15290 <1> ; 1) From the parent process number, the parent's 15291 <1> ; process name is found. The p.ppid table of parent 15292 <1> ; names is then searched for this process name. 15293 <1> ; If a match occurs, r2 contains child's process 15294 <1> ; number. The child status is checked to see if it is 15295 <1> ; a zombie, i.e; dead but not waited for (p.stat=3) 15296 <1> ; If it is, the child process is freed and it's name 15297 <1> ; is put in (u.r0). A return is then made via 'sysret'. 15298 <1> ; If the child is not a zombie, nothing happens and 15299 <1> ; the search goes on through the p.ppid table until 15300 <1> ; all processes are checked or a zombie is found. 15301 <1> ; 2) If no zombies are found, a check is made to see if 15302 <1> ; there are any children at all. If there are none, 15303 <1> ; an error return is made. If there are, the parent's 15304 <1> ; status is set to 2 (waiting for child to die), 15305 <1> ; the parent is swapped out, and a branch to 'syswait' 15306 <1> ; is made to wait on the next process. 15307 <1> ; 15308 <1> ; Calling sequence: 15309 <1> ; ? 15310 <1> ; Arguments: 15311 <1> ; - 15312 <1> ; Inputs: - 15313 <1> ; Outputs: if zombie found, it's name put in u.r0. 15314 <1> ; ............................................................... 15315 <1> ; 15316 <1> 15317 <1> ; / wait for a process to die 15318 <1> 15319 <1> syswait_0: 15320 0000332E 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 15321 <1> ; movb u.uno,r1 / put parents process number in r1 15322 00003335 D0E3 <1> shl bl, 1 15323 <1> ;shl bx, 1 15324 <1> ; asl r1 / x2 to get index into p.pid table 15325 00003337 668B83[62680000] <1> mov ax, [ebx+p.pid-2] 15326 <1> ; mov p.pid-2(r1),r1 / get the name of this process 15327 0000333E 31F6 <1> xor esi, esi 15328 <1> ; clr r2 15329 00003340 31C9 <1> xor ecx, ecx ; 30/10/2013 15330 <1> ;xor cl, cl 15331 <1> ; clr r3 / initialize reg 3 15332 <1> syswait_1: ; 1: 15333 <1> ; 09/02/2022 15334 00003342 46 <1> inc esi 15335 00003343 46 <1> inc esi 15336 <1> ;add si, 2 15337 <1> ; add $2,r2 / use r2 for index into p.ppid table 15338 <1> ; / search table of parent processes 15339 <1> ; / for this process name 15340 00003344 663B86[82680000] <1> cmp ax, [esi+p.ppid-2] 15341 <1> ; cmp p.ppid-2(r2),r1 / r2 will contain the childs 15342 <1> ; / process number 15343 0000334B 7531 <1> jne short syswait_3 15344 <1> ; bne 3f / branch if no match of parent process name 15345 <1> ;inc cx 15346 0000334D FEC1 <1> inc cl 15347 <1> ; inc r3 / yes, a match, r3 indicates number of children 15348 <1> ; 09/02/2022 15349 0000334F D1EE <1> shr esi, 1 15350 <1> ;shr si, 1 15351 <1> ; asr r2 / r2/2 to get index to p.stat table 15352 <1> ; The possible states ('p.stat' values) of a process are: 15353 <1> ; 0 = free or unused 15354 <1> ; 1 = active 15355 <1> ; 2 = waiting for a child process to die 15356 <1> ; 3 = terminated, but not yet waited for (zombie). 15357 00003351 80BE[C3680000]03 <1> cmp byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014 15358 <1> ; cmpb p.stat-1(r2),$3 / is the child process a zombie? 15359 00003358 7522 <1> jne short syswait_2 15360 <1> ; bne 2f / no, skip it 15361 0000335A 88BE[C3680000] <1> mov [esi+p.stat-1], bh ; 0 15362 <1> ; clrb p.stat-1(r2) / yes, free it 15363 <1> ; 09/02/2022 15364 00003360 D1E6 <1> shl esi, 1 15365 <1> ;shl si, 1 15366 <1> ; asl r2 / r2x2 to get index into p.pid table 15367 00003362 0FB786[62680000] <1> movzx eax, word [esi+p.pid-2] 15368 00003369 A3[A46C0000] <1> mov [u.r0], eax 15369 <1> ; mov p.pid-2(r2),*u.r0 15370 <1> ; / put childs process name in (u.r0) 15371 <1> ; 15372 <1> ; Retro UNIX 386 v1 modification ! (17/09/2015) 15373 <1> ; 15374 <1> ; Parent process ID -p.ppid- field (of the child process) 15375 <1> ; must be cleared in order to prevent infinitive 'syswait' 15376 <1> ; system call loop from the application/program if it calls 15377 <1> ; 'syswait' again (mistakenly) while there is not a zombie 15378 <1> ; or running child process to wait. ('forktest.s', 17/09/2015) 15379 <1> ; 15380 <1> ; Note: syswait will return with error if there is not a 15381 <1> ; zombie or running process to wait. 15382 <1> ; 15383 <1> ;sub ax, ax 15384 <1> ; 08/01/2022 15385 0000336E 29C0 <1> sub eax, eax 15386 00003370 668986[82680000] <1> mov [esi+p.ppid-2], ax ; 0 ; 17/09/2015 15387 00003377 E90BFEFFFF <1> jmp sysret0 ; ax = 0 15388 <1> ; 15389 <1> ;jmp sysret 15390 <1> ; br sysret1 / return cause child is dead 15391 <1> syswait_2: ; 2: 15392 <1> ; 09/02/2022 15393 0000337C D1E6 <1> shl esi, 1 15394 <1> ;shl si, 1 15395 <1> ; asl r2 / r2x2 to get index into p.ppid table 15396 <1> syswait_3: ; 3: 15397 0000337E 6683FE20 <1> cmp si, nproc+nproc 15398 <1> ; cmp r2,$nproc+nproc / have all processes been checked? 15399 00003382 72BE <1> jb short syswait_1 15400 <1> ; blt 1b / no, continue search 15401 <1> ;and cx, cx 15402 00003384 20C9 <1> and cl, cl 15403 <1> ; tst r3 / one gets here if there are no children 15404 <1> ; / or children that are still active 15405 <1> ; 30/10/2013 15406 00003386 7515 <1> jnz short syswait_4 15407 <1> ;jz error 15408 <1> ; beq error1 / there are no children, error 15409 00003388 890D[A46C0000] <1> mov [u.r0], ecx ; 0 15410 <1> ; 09/02/2022 15411 0000338E C705[186D0000]1B00- <1> mov dword [u.error], ERR_MISC ; 27 15412 00003396 0000 <1> 15413 <1> ; miscellaneous/other errors 15414 00003398 E9C8FDFFFF <1> jmp error 15415 <1> syswait_4: 15416 0000339D 8A1D[F56C0000] <1> mov bl, [u.uno] 15417 <1> ; movb u.uno,r1 / there are children so put 15418 <1> ; / parent process number in r1 15419 000033A3 FE83[C3680000] <1> inc byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014 15420 <1> ; incb p.stat-1(r1) / it is waiting for 15421 <1> ; / other children to die 15422 <1> ; 04/11/2013 15423 000033A9 E853120000 <1> call swap 15424 <1> ; jsr r0,swap / swap it out, because it's waiting 15425 000033AE E97BFFFFFF <1> jmp syswait_0 15426 <1> ; br syswait / wait on next process 15427 <1> 15428 <1> sysfork: ; < create a new process > 15429 <1> ; 27/02/2022 15430 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 15431 <1> ; 18/09/2015 15432 <1> ; 04/09/2015 15433 <1> ; 02/09/2015 15434 <1> ; 01/09/2015 15435 <1> ; 28/08/2015 15436 <1> ; 14/05/2015 15437 <1> ; 10/05/2015 15438 <1> ; 09/05/2015 15439 <1> ; 06/05/2015 (Retro UNIX 386 v1 - Beginning) 15440 <1> ; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1) 15441 <1> ; 15442 <1> ; 'sysfork' creates a new process. This process is referred 15443 <1> ; to as the child process. This new process core image is 15444 <1> ; a copy of that of the caller of 'sysfork'. The only 15445 <1> ; distinction is the return location and the fact that (u.r0) 15446 <1> ; in the old process (parent) contains the process id (p.pid) 15447 <1> ; of the new process (child). This id is used by 'syswait'. 15448 <1> ; 'sysfork' works in the following manner: 15449 <1> ; 1) The process status table (p.stat) is searched to find 15450 <1> ; a process number that is unused. If none are found 15451 <1> ; an error occurs. 15452 <1> ; 2) when one is found, it becomes the child process number 15453 <1> ; and it's status (p.stat) is set to active. 15454 <1> ; 3) If the parent had a control tty, the interrupt 15455 <1> ; character in that tty buffer is cleared. 15456 <1> ; 4) The child process is put on the lowest priority run 15457 <1> ; queue via 'putlu'. 15458 <1> ; 5) A new process name is gotten from 'mpid' (actually 15459 <1> ; it is a unique number) and is put in the child's unique 15460 <1> ; identifier; process id (p.pid). 15461 <1> ; 6) The process name of the parent is then obtained and 15462 <1> ; placed in the unique identifier of the parent process 15463 <1> ; name is then put in 'u.r0'. 15464 <1> ; 7) The child process is then written out on disk by 15465 <1> ; 'wswap',i.e., the parent process is copied onto disk 15466 <1> ; and the child is born. (The child process is written 15467 <1> ; out on disk/drum with 'u.uno' being the child process 15468 <1> ; number.) 15469 <1> ; 8) The parent process number is then restored to 'u.uno'. 15470 <1> ; 9) The child process name is put in 'u.r0'. 15471 <1> ; 10) The pc on the stack sp + 18 is incremented by 2 to 15472 <1> ; create the return address for the parent process. 15473 <1> ; 11) The 'u.fp' list as then searched to see what files 15474 <1> ; the parent has opened. For each file the parent has 15475 <1> ; opened, the corresponding 'fsp' entry must be updated 15476 <1> ; to indicate that the child process also has opened 15477 <1> ; the file. A branch to 'sysret' is then made. 15478 <1> ; 15479 <1> ; Calling sequence: 15480 <1> ; from shell ? 15481 <1> ; Arguments: 15482 <1> ; - 15483 <1> ; Inputs: - 15484 <1> ; Outputs: *u.r0 - child process name 15485 <1> ; ............................................................... 15486 <1> ; 15487 <1> ; Retro UNIX 8086 v1 modification: 15488 <1> ; AX = r0 = PID (>0) (at the return of 'sysfork') 15489 <1> ; = process id of child a parent process returns 15490 <1> ; = process id of parent when a child process returns 15491 <1> ; 15492 <1> ; In original UNIX v1, sysfork is called and returns as 15493 <1> ; in following manner: (with an example: c library, fork) 15494 <1> ; 15495 <1> ; 1: 15496 <1> ; sys fork 15497 <1> ; br 1f / child process returns here 15498 <1> ; bes 2f / parent process returns here 15499 <1> ; / pid of new process in r0 15500 <1> ; rts pc 15501 <1> ; 2: / parent process condionally branches here 15502 <1> ; mov $-1,r0 / pid = -1 means error return 15503 <1> ; rts pc 15504 <1> ; 15505 <1> ; 1: / child process brances here 15506 <1> ; clr r0 / pid = 0 in child process 15507 <1> ; rts pc 15508 <1> ; 15509 <1> ; In UNIX v7x86 (386) by Robert Nordier (1999) 15510 <1> ; // pid = fork(); 15511 <1> ; // 15512 <1> ; // pid == 0 in child process; 15513 <1> ; // pid == -1 means error return 15514 <1> ; // in child, 15515 <1> ; // parents id is in par_uid if needed 15516 <1> ; 15517 <1> ; _fork: 15518 <1> ; mov $.fork,eax 15519 <1> ; int $0x30 15520 <1> ; jmp 1f 15521 <1> ; jnc 2f 15522 <1> ; jmp cerror 15523 <1> ; 1: 15524 <1> ; mov eax,_par_uid 15525 <1> ; xor eax,eax 15526 <1> ; 2: 15527 <1> ; ret 15528 <1> ; 15529 <1> ; In Retro UNIX 8086 v1, 15530 <1> ; 'sysfork' returns in following manner: 15531 <1> ; 15532 <1> ; mov ax, sys_fork 15533 <1> ; mov bx, offset @f ; routine for child 15534 <1> ; int 20h 15535 <1> ; jc error 15536 <1> ; 15537 <1> ; ; Routine for parent process here (just after 'jc') 15538 <1> ; mov word ptr [pid_of_child], ax 15539 <1> ; jmp next_routine_for_parent 15540 <1> ; 15541 <1> ; @@: ; routine for child process here 15542 <1> ; .... 15543 <1> ; NOTE: 'sysfork' returns to specified offset 15544 <1> ; for child process by using BX input. 15545 <1> ; (at first, parent process will return then 15546 <1> ; child process will return -after swapped in- 15547 <1> ; 'syswait' is needed in parent process 15548 <1> ; if return from child process will be waited for.) 15549 <1> ; 15550 <1> 15551 <1> ; / create a new process 15552 <1> ; EBX = return address for child process 15553 <1> ; (Retro UNIX 8086 v1 modification !) 15554 000033B3 31F6 <1> xor esi, esi 15555 <1> ; clr r1 15556 <1> sysfork_1: ; 1: / search p.stat table for unused process number 15557 000033B5 46 <1> inc esi 15558 <1> ; inc r1 15559 000033B6 80BE[C3680000]00 <1> cmp byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014 15560 <1> ; tstb p.stat-1(r1) / is process active, unused, dead 15561 000033BD 760B <1> jna short sysfork_2 15562 <1> ; beq 1f / it's unused so branch 15563 000033BF 6683FE10 <1> cmp si, nproc 15564 <1> ; cmp r1,$nproc / all processes checked 15565 000033C3 72F0 <1> jb short sysfork_1 15566 <1> ; blt 1b / no, branch back 15567 <1> ; 15568 <1> ; Retro UNIX 8086 v1. modification: 15569 <1> ; Parent process returns from 'sysfork' to address 15570 <1> ; which is just after 'sysfork' system call in parent 15571 <1> ; process. Child process returns to address which is put 15572 <1> ; in BX register by parent process for 'sysfork'. 15573 <1> ; 15574 <1> ; add $2,18.(sp) / add 2 to pc when trap occured, points 15575 <1> ; / to old process return 15576 <1> ; br error1 / no room for a new process 15577 <1> sysfork_0: 15578 000033C5 E99BFDFFFF <1> jmp error 15579 <1> sysfork_2: ; 1: 15580 000033CA E810F0FFFF <1> call allocate_page 15581 <1> ;jc error 15582 <1> ; 08/01/2022 15583 000033CF 72F4 <1> jc short sysfork_0 15584 <1> 15585 000033D1 50 <1> push eax ; UPAGE (user structure page) address 15586 <1> ; Retro UNIX 386 v1 modification! 15587 000033D2 E8FFF1FFFF <1> call duplicate_page_dir 15588 <1> ; EAX = New page directory 15589 000033D7 7308 <1> jnc short sysfork_3 15590 000033D9 58 <1> pop eax ; UPAGE (user structure page) address 15591 000033DA E8C6F1FFFF <1> call deallocate_page 15592 <1> ;jmp error 15593 <1> ; 08/01/2022 15594 000033DF EBE4 <1> jmp short sysfork_0 ; error 15595 <1> sysfork_3: 15596 <1> ; Retro UNIX 386 v1 modification ! 15597 000033E1 56 <1> push esi 15598 000033E2 E891120000 <1> call wswap ; save current user (u) structure, user registers 15599 <1> ; and interrupt return components (for IRET) 15600 000033E7 8705[046D0000] <1> xchg eax, [u.pgdir] ; page directory of the child process 15601 000033ED A3[086D0000] <1> mov [u.ppgdir], eax ; page directory of the parent process 15602 000033F2 5E <1> pop esi 15603 000033F3 58 <1> pop eax ; UPAGE (user structure page) address 15604 <1> ; [u.usp] = esp 15605 000033F4 89F7 <1> mov edi, esi 15606 <1> ;shl di, 2 15607 <1> ; 08/01/2022 15608 000033F6 C1E702 <1> shl edi, 2 15609 000033F9 8987[D0680000] <1> mov [edi+p.upage-4], eax ; memory page for 'user' struct 15610 000033FF A3[006D0000] <1> mov [u.upage], eax ; memory page for 'user' struct (child) 15611 <1> ; 28/08/2015 15612 00003404 0FB605[F56C0000] <1> movzx eax, byte [u.uno] ; parent process number 15613 <1> ; movb u.uno,-(sp) / save parent process number 15614 0000340B 89C7 <1> mov edi, eax 15615 0000340D 50 <1> push eax ; ** 15616 0000340E 8A87[A3680000] <1> mov al, [edi+p.ttyc-1] ; console tty (parent) 15617 <1> ; 18/09/2015 (27/02/2022) 15618 00003414 8886[A3680000] <1> mov [esi+p.ttyc-1], al ; set child's console tty 15619 <1> ; 27/02/2022 (p.waitc is not used) 15620 <1> ;mov [esi+p.waitc-1], ah ; 0 ; reset child's wait channel 15621 <1> ; 27/02/2022 (BugFix) 15622 <1> ;mov [esi+p.ttyc-1], ax ; al - set child's console tty 15623 <1> ; ; ah - reset child's wait channel 15624 0000341A 89F0 <1> mov eax, esi 15625 0000341C A2[F56C0000] <1> mov [u.uno], al ; child process number 15626 <1> ;movb r1,u.uno / set child process number to r1 15627 00003421 FE86[C3680000] <1> inc byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014 15628 <1> ; incb p.stat-1(r1) / set p.stat entry for child 15629 <1> ; / process to active status 15630 <1> ; mov u.ttyp,r2 / put pointer to parent process' 15631 <1> ; / control tty buffer in r2 15632 <1> ; beq 2f / branch, if no such tty assigned 15633 <1> ; clrb 6(r2) / clear interrupt character in tty buffer 15634 <1> ; 2: 15635 00003427 53 <1> push ebx ; * return address for the child process 15636 <1> ; * Retro UNIX 8086 v1 feature only ! 15637 <1> ; (Retro UNIX 8086 v1 modification!) 15638 <1> ; mov $runq+4,r2 15639 00003428 E8A1120000 <1> call putlu 15640 <1> ; jsr r0,putlu / put child process on lowest priority 15641 <1> ; / run queue 15642 <1> ; 08/01/2022 15643 0000342D D1E6 <1> shl esi, 1 15644 <1> ;shl si, 1 15645 <1> ; asl r1 / multiply r1 by 2 to get index 15646 <1> ; / into p.pid table 15647 0000342F 66FF05[846C0000] <1> inc word [mpid] 15648 <1> ; inc mpid / increment m.pid; get a new process name 15649 00003436 66A1[846C0000] <1> mov ax, [mpid] 15650 0000343C 668986[62680000] <1> mov [esi+p.pid-2], ax 15651 <1> ;mov mpid,p.pid-2(r1) / put new process name 15652 <1> ; / in child process' name slot 15653 00003443 5A <1> pop edx ; * return address for the child process 15654 <1> ; * Retro UNIX 8086 v1 feature only ! 15655 00003444 5B <1> pop ebx ; ** 15656 <1> ;mov ebx, [esp] ; ** parent process number 15657 <1> ; movb (sp),r2 / put parent process number in r2 15658 <1> ; 08/01/2022 15659 00003445 D1E3 <1> shl ebx, 1 15660 <1> ;shl bx, 1 15661 <1> ; asl r2 / multiply by 2 to get index into below tables 15662 <1> ;movzx eax, word [ebx+p.pid-2] 15663 00003447 668B83[62680000] <1> mov ax, [ebx+p.pid-2] 15664 <1> ; mov p.pid-2(r2),r2 / get process name of parent 15665 <1> ; / process 15666 0000344E 668986[82680000] <1> mov [esi+p.ppid-2], ax 15667 <1> ; mov r2,p.ppid-2(r1) / put parent process name 15668 <1> ; / in parent process slot for child 15669 00003455 A3[A46C0000] <1> mov [u.r0], eax 15670 <1> ; mov r2,*u.r0 / put parent process name on stack 15671 <1> ; / at location where r0 was saved 15672 0000345A 8B2D[9C6C0000] <1> mov ebp, [u.sp] ; points to return address (EIP for IRET) 15673 00003460 895500 <1> mov [ebp], edx ; *, CS:EIP -> EIP 15674 <1> ; * return address for the child process 15675 <1> ; mov $sysret1,-(sp) / 15676 <1> ; mov sp,u.usp / contents of sp at the time when 15677 <1> ; / user is swapped out 15678 <1> ; mov $sstack,sp / point sp to swapping stack space 15679 <1> ; 04/09/2015 - 01/09/2015 15680 <1> ; [u.usp] = esp 15681 00003463 68[85310000] <1> push sysret ; *** 15682 00003468 8925[A06C0000] <1> mov [u.usp], esp ; points to 'sysret' address (***) 15683 <1> ; (for child process) 15684 0000346E 31C0 <1> xor eax, eax 15685 00003470 66A3[DA6C0000] <1> mov [u.ttyp], ax ; 0 15686 <1> ; 15687 00003476 E8FD110000 <1> call wswap ; Retro UNIX 8086 v1 modification ! 15688 <1> ;jsr r0,wswap / put child process out on drum 15689 <1> ;jsr r0,unpack / unpack user stack 15690 <1> ;mov u.usp,sp / restore user stack pointer 15691 <1> ; tst (sp)+ / bump stack pointer 15692 <1> ; Retro UNIX 386 v1 modification ! 15693 0000347B 58 <1> pop eax ; *** 15694 <1> ; 08/01/2022 15695 0000347C D1E3 <1> shl ebx, 1 15696 <1> ;shl bx, 1 15697 0000347E 8B83[D0680000] <1> mov eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015 15698 00003484 E818120000 <1> call rswap ; restore parent process 'u' structure, 15699 <1> ; registers and return address (for IRET) 15700 <1> ;movb (sp)+,u.uno / put parent process number in u.uno 15701 00003489 0FB705[846C0000] <1> movzx eax, word [mpid] 15702 00003490 A3[A46C0000] <1> mov [u.r0], eax 15703 <1> ; mov mpid,*u.r0 / put child process name on stack 15704 <1> ; / where r0 was saved 15705 <1> ; add $2,18.(sp) / add 2 to pc on stack; gives parent 15706 <1> ; / process return 15707 <1> ;xor ebx, ebx 15708 00003495 31F6 <1> xor esi, esi 15709 <1> ;clr r1 15710 <1> sysfork_4: ; 1: / search u.fp list to find the files 15711 <1> ; / opened by the parent process 15712 <1> ; 08/01/2022 15713 <1> ; 01/09/2015 15714 00003497 30FF <1> xor bh, bh 15715 00003499 8A9E[AE6C0000] <1> mov bl, [esi+u.fp] 15716 <1> ; 08/01/2022 15717 <1> ;mov al, [esi+u.fp] 15718 <1> ; movb u.fp(r1),r2 / get an open file for this process 15719 0000349F 08DB <1> or bl, bl 15720 <1> ; 08/01/2022 15721 <1> ;or al, al 15722 000034A1 7409 <1> jz short sysfork_5 15723 <1> ; beq 2f / file has not been opened by parent, 15724 <1> ; / so branch 15725 <1> ;mov ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes 15726 <1> ; 08/01/2022 15727 <1> ;mov ah, 16 ; Retro UNIX 386 v2 fsp structure size = 16 bytes 15728 <1> ;mul ah 15729 <1> ;;movzx ebx, ax 15730 <1> ;mov bx, ax 15731 <1> ;mov ebx, eax ; 08/01/2022 15732 <1> ;shl bx, 3 15733 <1> ; asl r2 / multiply by 8 15734 <1> ; asl r2 / to get index into fsp table 15735 <1> ; asl r2 15736 <1> ; 08/01/2022 15737 000034A3 C1E304 <1> shl ebx, 4 ; multiply by 16 15738 <1> ; 08/01/2022 15739 000034A6 FE83[0A690000] <1> inc byte [ebx+fsp-10] ; Retro UNIX 386 v2 fs fsp structure 15740 <1> ;inc byte [ebx+fsp-2] 15741 <1> ; incb fsp-2(r2) / increment number of processes 15742 <1> ; / using file, because child will now be 15743 <1> ; / using this file 15744 <1> sysfork_5: ; 2: 15745 000034AC 46 <1> inc esi 15746 <1> ; inc r1 / get next open file 15747 000034AD 6683FE0A <1> cmp si, 10 15748 <1> ; cmp r1,$10. / 10. files is the maximum number which 15749 <1> ; / can be opened 15750 000034B1 72E4 <1> jb short sysfork_4 15751 <1> ; blt 1b / check next entry 15752 000034B3 E9CDFCFFFF <1> jmp sysret 15753 <1> ; br sysret1 15754 <1> 15755 <1> sysread: ; < read from file > 15756 <1> ; 24/12/2021 15757 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 15758 <1> ; 27/03/2020 15759 <1> ; 26/03/2020 - Retro UNIX 386 v2 15760 <1> ; 13/05/2015 15761 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 15762 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 15763 <1> ; 15764 <1> ; 'sysread' is given a buffer to read into and the number of 15765 <1> ; characters to be read. If finds the file from the file 15766 <1> ; descriptor located in *u.r0 (r0). This file descriptor 15767 <1> ; is returned from a successful open call (sysopen). 15768 <1> ; The i-number of file is obtained via 'rw1' and the data 15769 <1> ; is read into core via 'readi'. 15770 <1> ; 15771 <1> ; Calling sequence: 15772 <1> ; sysread; buffer; nchars 15773 <1> ; Arguments: 15774 <1> ; buffer - location of contiguous bytes where 15775 <1> ; input will be placed. 15776 <1> ; nchars - number of bytes or characters to be read. 15777 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 15778 <1> ; Outputs: *u.r0 - number of bytes read. 15779 <1> ; ............................................................... 15780 <1> ; 15781 <1> ; Retro UNIX 8086 v1 modification: 15782 <1> ; 'sysread' system call has three arguments; so, 15783 <1> ; * 1st argument, file descriptor is in BX register 15784 <1> ; * 2nd argument, buffer address/offset in CX register 15785 <1> ; * 3rd argument, number of bytes is in DX register 15786 <1> ; 15787 <1> ; AX register (will be restored via 'u.r0') will return 15788 <1> ; to the user with number of bytes read. 15789 <1> ; 15790 <1> 15791 000034B8 E839000000 <1> call rw1 15792 <1> ;jc error ; 13/05/2015, ax < 1 15793 <1> ; ; jsr r0,rw1 / get i-number of file to be read into r1 15794 <1> ; 04/12/2021 15795 000034BD 7209 <1> jc short sysread_err 15796 000034BF 7529 <1> jnz short rw3 ; error ! (permission denied) 15797 <1> ; ; read a file while it is open for write! 15798 <1> 15799 <1> ; eax = inode number 15800 <1> 15801 <1> ; 04/12/2021 15802 <1> ;((Retro Unix 386 v1 code)) (old code below) 15803 <1> ;test ah, 80h 15804 <1> ; ; tst r1 / negative i-number? 15805 <1> ;;jnz error 15806 <1> ;; ; ble error1 / yes, error 1 to read 15807 <1> ;; ; / it should be positive 15808 <1> ;; 04/12/2021 15809 <1> ;jnz short sysread_err 15810 <1> 15811 000034C1 E81B1A0000 <1> call readi 15812 <1> ; jsr r0,readi / read data into core 15813 000034C6 EB13 <1> jmp short rw0 15814 <1> ; br 1f 15815 <1> sysread_err: 15816 <1> syswrite_err: 15817 <1> ; 04/12/2021 15818 000034C8 E998FCFFFF <1> jmp error 15819 <1> 15820 <1> syswrite: ; < write to file > 15821 <1> ; 24/12/2021 15822 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 15823 <1> ; 27/03/2020 15824 <1> ; 26/03/2020 - Retro UNIX 386 v2 15825 <1> ; 13/05/2015 15826 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 15827 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 15828 <1> ; 15829 <1> ; 'syswrite' is given a buffer to write onto an output file 15830 <1> ; and the number of characters to write. If finds the file 15831 <1> ; from the file descriptor located in *u.r0 (r0). This file 15832 <1> ; descriptor is returned from a successful open or create call 15833 <1> ; (sysopen or syscreat). The i-number of file is obtained via 15834 <1> ; 'rw1' and buffer is written on the output file via 'write'. 15835 <1> ; 15836 <1> ; Calling sequence: 15837 <1> ; syswrite; buffer; nchars 15838 <1> ; Arguments: 15839 <1> ; buffer - location of contiguous bytes to be writtten. 15840 <1> ; nchars - number of characters to be written. 15841 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 15842 <1> ; Outputs: *u.r0 - number of bytes written. 15843 <1> ; ............................................................... 15844 <1> ; 15845 <1> ; Retro UNIX 8086 v1 modification: 15846 <1> ; 'syswrite' system call has three arguments; so, 15847 <1> ; * 1st argument, file descriptor is in BX register 15848 <1> ; * 2nd argument, buffer address/offset in CX register 15849 <1> ; * 3rd argument, number of bytes is in DX register 15850 <1> ; 15851 <1> ; AX register (will be restored via 'u.r0') will return 15852 <1> ; to the user with number of bytes written. 15853 <1> ; 15854 <1> 15855 000034CD E824000000 <1> call rw1 15856 <1> ;jc error ; 13/05/2015, ax < 1 15857 <1> ; ; jsr r0,rw1 / get i-number in r1 of file to write 15858 <1> ; 04/12/2021 15859 000034D2 72F4 <1> jc short syswrite_err 15860 000034D4 7414 <1> jz short rw3 ; error ! (permission denied) 15861 <1> ; write to a file while it is open for read 15862 <1> ; eax = inode number 15863 <1> 15864 <1> ; 04/12/2021 15865 <1> ;((Retro Unix 386 v1 code)) (old code below) 15866 <1> ;test ah, 80h 15867 <1> ; ; tst r1 / positive i-number ? 15868 <1> ;jz short rw3 ; 13/05/2015 15869 <1> ;;jz error 15870 <1> ; ; bge error1 / yes, error 1 15871 <1> ; ; / negative i-number means write 15872 <1> ;neg ax 15873 <1> ; ; neg r1 / make it positive 15874 <1> 15875 000034D6 E81A1C0000 <1> call writei 15876 <1> ; jsr r0,writei / write data 15877 <1> rw0: ; 1: 15878 000034DB A1[D06C0000] <1> mov eax, [u.nread] 15879 000034E0 A3[A46C0000] <1> mov [u.r0], eax 15880 <1> ; mov u.nread,*u.r0 / put no. of bytes transferred 15881 <1> ; / into (u.r0) 15882 000034E5 E99BFCFFFF <1> jmp sysret 15883 <1> ; br sysret1 15884 <1> rw3: 15885 <1> ; 13/05/2015 15886 000034EA C705[186D0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 15887 000034F2 0000 <1> 15888 <1> ;stc 15889 <1> ;retn 15890 <1> ; 24/12/2021 - Retro UNIX 386 v1.2 15891 000034F4 EBD2 <1> jmp short syswrite_err 15892 <1> 15893 <1> rw1: 15894 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 15895 <1> ; 27/03/2020 15896 <1> ; 26/03/2020 - Retro UNIX 386 v2 15897 <1> ; 14/05/2015 15898 <1> ; 13/05/2015 15899 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 15900 <1> ; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1) 15901 <1> ; System call registers: bx, cx, dx (through 'sysenter') 15902 <1> ; 15903 <1> ;mov [u.base], ecx ; buffer address/offset 15904 <1> ;(in the user's virtual memory space) 15905 <1> ;mov [u.count], edx 15906 <1> ; jsr r0,arg; u.base / get buffer pointer 15907 <1> ; jsr r0,arg; u.count / get no. of characters 15908 <1> ;;mov eax, ebx ; file descriptor 15909 <1> ; mov *u.r0,r1 / put file descriptor 15910 <1> ; / (index to u.fp table) in r1 15911 <1> ; 13/05/2015 15912 000034F6 C705[A46C0000]0000- <1> mov dword [u.r0], 0 ; r/w transfer count = 0 (reset) 15913 000034FE 0000 <1> 15914 <1> ; 15915 <1> ;; call getf 15916 <1> ; ebx = File descriptor 15917 00003500 E8410B0000 <1> call getf1 ; calling point in 'getf' from 'rw1' 15918 <1> ; jsr r0,getf / get i-number of the file in r1 15919 <1> ; AX = I-number of the file ; negative i-number means write 15920 <1> 15921 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 15922 <1> ; 26/03/2020 - Retro UNIX 386 v2 15923 <1> ; BL = open mode & status flag (0 = read, 1 = write) 15924 <1> ; eax = inode number (ax) 15925 <1> ; 27/03/2020 15926 <1> ; [cdev] = logical drive number 15927 <1> 15928 <1> ; 13/05/2015 15929 00003505 6683F801 <1> cmp ax, 1 15930 00003509 721A <1> jb short rw2 15931 <1> ; 15932 0000350B 890D[C86C0000] <1> mov [u.base], ecx ; buffer address/offset 15933 <1> ;(in the user's virtual memory space) 15934 00003511 8915[CC6C0000] <1> mov [u.count], edx 15935 <1> ; 14/05/2015 15936 00003517 C705[186D0000]0000- <1> mov dword [u.error], 0 ; reset the last error code 15937 0000351F 0000 <1> 15938 <1> 15939 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 15940 <1> ; 27/03/2020 - Retro UNIX 386 v2 15941 00003521 80E301 <1> and bl, 1 15942 <1> ; zf = 0 -> open for write 15943 <1> ; zf = 1 -> open for read 15944 00003524 C3 <1> retn 15945 <1> ; rts r0 15946 <1> rw2: 15947 <1> ; 13/05/2015 15948 00003525 C705[186D0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 15949 0000352D 0000 <1> 15950 0000352F C3 <1> retn 15951 <1> 15952 <1> ; 18/04/2022 15953 <1> ; 08/01/2022 15954 <1> ; 02/01/2022 15955 <1> ; 01/01/2022 15956 <1> ; 27/12/2021 15957 <1> ; 22/11/2021 - Retro UNIX 386 v2 fs compatibility code 15958 <1> sysopen: ; 15959 <1> ; 04/12/2021 15960 <1> ; 07/08/2020 (Retro UNIX 386 v2) 15961 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 15962 <1> ; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1) 15963 <1> ; 15964 <1> ; 'sysopen' opens a file in following manner: 15965 <1> ; 1) The second argument in a sysopen says whether to 15966 <1> ; open the file ro read (0) or write (>0). 15967 <1> ; 2) I-node of the particular file is obtained via 'namei'. 15968 <1> ; 3) The file is opened by 'iopen'. 15969 <1> ; 4) Next housekeeping is performed on the fsp table 15970 <1> ; and the user's open file list - u.fp. 15971 <1> ; a) u.fp and fsp are scanned for the next available slot. 15972 <1> ; b) An entry for the file is created in the fsp table. 15973 <1> ; c) The number of this entry is put on u.fp list. 15974 <1> ; d) The file descriptor index to u.fp list is pointed 15975 <1> ; to by u.r0. 15976 <1> ; 15977 <1> ; Calling sequence: 15978 <1> ; sysopen; name; mode 15979 <1> ; Arguments: 15980 <1> ; name - file name or path name 15981 <1> ; mode - 0 to open for reading 15982 <1> ; 1 to open for writing 15983 <1> ; Inputs: (arguments) 15984 <1> ; Outputs: *u.r0 - index to u.fp list (the file descriptor) 15985 <1> ; is put into r0's location on the stack. 15986 <1> ; ............................................................... 15987 <1> ; 15988 <1> ; Retro UNIX 8086 v1 modification: 15989 <1> ; 'sysopen' system call has two arguments; so, 15990 <1> ; * 1st argument, name is pointed to by BX register 15991 <1> ; * 2nd argument, mode is in CX register 15992 <1> ; 15993 <1> ; AX register (will be restored via 'u.r0') will return 15994 <1> ; to the user with the file descriptor/number 15995 <1> ; (index to u.fp list). 15996 <1> ; 15997 <1> ;call arg2 15998 <1> ; * name - 'u.namep' points to address of file/path name 15999 <1> ; in the user's program segment ('u.segmnt') 16000 <1> ; with offset in BX register (as sysopen argument 1). 16001 <1> ; * mode - sysopen argument 2 is in CX register 16002 <1> ; which is on top of stack. 16003 <1> ; 16004 <1> ; jsr r0,arg2 / get sys args into u.namep and on stack 16005 <1> ; 16006 <1> ; system call registers: ebx, ecx (through 'sysenter') 16007 <1> 16008 00003530 891D[C06C0000] <1> mov [u.namep], ebx 16009 00003536 51 <1> push ecx ; * ; 04/12/2021 (cx -> ecx) 16010 00003537 E8400B0000 <1> call namei 16011 <1> ; jsr r0,namei / i-number of file in r1 16012 <1> ;and ax, ax 16013 <1> ;jz error ; File not found 16014 0000353C 722B <1> jc short fnotfound ; 14/05/2015 16015 <1> ;jc error ; 27/05/2013 16016 <1> ; br error2 / file not found 16017 <1> ;pop edx ; * ; mode ; 04/12/2021 16018 <1> ;push edx ; * 16019 <1> ;;or dx, dx 16020 <1> ;or dl, dl 16021 <1> ; ; tst (sp) / is mode = 0 (2nd arg of call; 16022 <1> ; ; / 0 means, open for read) 16023 <1> ;;jz short sysopen_0 16024 <1> ;; ; beq 1f / yes, leave i-number positive 16025 <1> 16026 0000353E 8B1424 <1> mov edx, [esp] ; * 16027 <1> ; edx = open mode (0 or 1) 16028 <1> 16029 <1> ;syscreat_0: ;op0: ; 27/12/2015 16030 <1> ; neg ax 16031 <1> ; ; neg r1 / open for writing so make i-number negative 16032 <1> 16033 <1> sysopen_0: ;1: 16034 00003541 E8A0200000 <1> call iopen 16035 <1> ; jsr r0,iopen / open file whose i-number is in r1 16036 00003546 5A <1> pop edx ; * ; mode ; 04/12/2021 16037 <1> ;;and dx, dx 16038 <1> ;and dl, dl 16039 <1> ; ; tst (sp)+ / pop the stack and test the mode 16040 <1> ;jz short sysopen_2 16041 <1> ; ; beq op1 / is open for read op1 16042 <1> ;sysopen_1: ;op0: 16043 <1> ;neg ax 16044 <1> ; ; neg r1 16045 <1> ; ;/ make i-number positive if open for writing [???] 16046 <1> 16047 <1> ;; NOTE: iopen always make i-number positive. 16048 <1> ;; Here i-number becomes negative again. [22/05/2013] 16049 <1> sysopen_1: ; 04/12/2021 16050 <1> sysopen_2: ;op1: 16051 00003547 31F6 <1> xor esi, esi 16052 <1> ; clr r2 / clear registers 16053 00003549 31DB <1> xor ebx, ebx 16054 <1> ; clr r3 16055 <1> sysopen_3: ;1: / scan the list of entries in fsp table 16056 0000354B 389E[AE6C0000] <1> cmp [esi+u.fp], bl ; 0 16057 <1> ; tstb u.fp(r2) / test the entry in the u.fp list 16058 00003551 7625 <1> jna short sysopen_4 16059 <1> ; beq 1f / if byte in list is 0 branch 16060 00003553 46 <1> inc esi 16061 <1> ; inc r2 / bump r2 so next byte can be checked 16062 <1> ; 02/01/2022 16063 <1> ;cmp si, OPENFILES ; 04/12/2021 16064 00003554 6683FE0A <1> cmp si, 10 16065 <1> ; cmp r2,$10. / reached end of list? 16066 00003558 72F1 <1> jb short sysopen_3 16067 <1> ; blt 1b / no, go back 16068 <1> toomanyf: 16069 <1> ; 14/05/2015 16070 0000355A C705[186D0000]0D00- <1> mov dword [u.error], ERR_TOO_MANY_FILES ; too many open files ! 16071 00003562 0000 <1> 16072 00003564 E9FCFBFFFF <1> jmp error 16073 <1> ; br error2 / yes, error (no files open) 16074 <1> fnotfound: 16075 <1> ; 14/05/2015 16076 00003569 C705[186D0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; file not found ! 16077 00003571 0000 <1> 16078 00003573 E9EDFBFFFF <1> jmp error 16079 <1> 16080 <1> sysopen_4: ; 1: 16081 00003578 6683BB[14690000]00 <1> cmp word [ebx+fsp], 0 16082 <1> ; tst fsp(r3) / scan fsp entries 16083 00003580 760D <1> jna short sysopen_5 16084 <1> ; beq 1f / if 0 branch 16085 <1> ;; 14/05/2015 - Retro UNIX 386 v1 modification ! 16086 <1> ;add bx, 10 ; fsp structure size = 10 bytes/entry 16087 <1> ; add $8.,r3 / add 8 to r3 16088 <1> ; / to bump it to next entry mfsp table 16089 <1> ; 01/01/2022 16090 <1> ; 07/08/2020 - Retro UNIX 386 v2 16091 00003582 6683C310 <1> add bx, 16 ; fsp structure size = 16 bytes/entry ; runix v2 16092 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 16093 <1> ;add bx, fp.size 16094 <1> 16095 <1> ; 22/11/2021 16096 <1> ;cmp bx, NFILES*fp.size ; NFILES*16 16097 <1> ; 02/01/2022 16098 00003586 6681FB2003 <1> cmp bx, nfiles*16 16099 <1> ; 01/01/2022 16100 <1> ;cmp bx, NFILES*16 ; NFILES*fp.size 16101 <1> ;;cmp bx, nfiles*10 16102 <1> ; cmp r3,$[nfiles*8.] / done scanning 16103 0000358B 72EB <1> jb short sysopen_4 16104 <1> ; blt 1b / no, back 16105 <1> ;jmp error 16106 <1> ; ; br error2 / yes, error 16107 <1> ; 04/12/2021 16108 <1> ; 07/08/2020 16109 0000358D EBCB <1> jmp short toomanyf 16110 <1> 16111 <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table 16112 0000358F 668983[14690000] <1> mov [ebx+fsp], ax 16113 <1> ; mov r1,fsp(r3) / put i-number of open file 16114 <1> ; / into next available entry in fsp table, 16115 <1> ;mov di, [cdev] ; word ? byte ? 16116 <1> ;mov [ebx+fsp+2], di ; device number 16117 <1> ; ; mov cdev,fsp+2(r3) / put # of device in next word 16118 <1> 16119 <1> ; 18/04/2022 16120 <1> ; 04/12/2021 16121 <1> ;mov al, [cdev] 16122 <1> ;mov ah, dl ; open mode, 0 = read, 1 = write 16123 <1> ;mov [ebx+fsp+4], ax ; device number & open mode 16124 <1> 16125 <1> ;xor edi, edi 16126 <1> ;mov [ebx+fsp+4], edi ; offset pointer (0) 16127 <1> ; ; clr fsp+4(r3) 16128 <1> ;mov [ebx+fsp+8], di ; open count (0), deleted flag (0) 16129 <1> ; ; clr fsp+6(r3) / clear the next two words 16130 <1> 16131 <1> ; 04/12/2021 16132 00003596 31C0 <1> xor eax, eax 16133 00003598 8983[1C690000] <1> mov [ebx+fsp+8], eax ; offset pointer = 0 16134 <1> 16135 <1> ;;inc word [ebx+fsp+6] 16136 <1> ;inc byte [ebx+fsp+6] ; open count = open count + 1 16137 <1> ; 18/04/2022 16138 <1> ;mov word [ebx+fsp+6], ax ; open count = 0 16139 <1> ; (sysfork increases open count) 16140 <1> ; 18/04/2022 ; reserved (mnt) flag = 0 16141 0000359E A0[816C0000] <1> mov al, [cdev] 16142 000035A3 88D4 <1> mov ah, dl ; open mode, 0 = read, 1 = write 16143 000035A5 8983[18690000] <1> mov [ebx+fsp+4], eax ; device number (al) 16144 <1> ; & open mode (ah) 16145 <1> ; (& open count = 0) 16146 <1> ;mov eax, ebx 16147 <1> ;mov bl, 10 16148 <1> ;div bl 16149 <1> ; ; asr r3 16150 <1> ; ; asr r3 / divide by 8 16151 <1> ; ; asr r3 ; / to get number of the fsp entry-1 16152 <1> ;inc al 16153 <1> ; ; inc r3 / add 1 to get fsp entry number 16154 <1> ;mov [esi+u.fp], al 16155 <1> ; ; movb r3,u.fp(r2) / move entry number into 16156 <1> ; / next available slot in u.fp list 16157 <1> ; 04/12/2021 16158 000035AB C1EB04 <1> shr ebx, 4 ; / 16 16159 <1> ;shr bx, 4 ; bx = fsp entry number (index) 16160 <1> ; bx <= 49 for current runix 386 version 16161 000035AE FEC3 <1> inc bl ; bl = 1 to 50 16162 000035B0 889E[AE6C0000] <1> mov [esi+u.fp], bl 16163 <1> 16164 000035B6 8935[A46C0000] <1> mov [u.r0], esi 16165 <1> ; mov r2,*u.r0 / move index to u.fp list 16166 <1> ; / into r0 loc on stack 16167 000035BC E9C4FBFFFF <1> jmp sysret 16168 <1> ; br sysret2 16169 <1> 16170 <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 16171 <1> ; 16172 <1> ; 15 7 0 16173 <1> ; 1 |-------------------------------------------| 16174 <1> ; | i-number of open file | 16175 <1> ; |-------------------------------------------| 16176 <1> ; | high word of 32 bit i-number | 16177 <1> ; |-------------------------------------------| 16178 <1> ; | open mode & status | device number | 16179 <1> ; |-------------------------------------------| 16180 <1> ; | reserved byte | open count | 16181 <1> ; |-------------------------------------------| 16182 <1> ; | offset pointer, i.e., r/w pointer to file | 16183 <1> ; |-------------------------------------------| 16184 <1> ; | 64 bit file offset pointer (bit 16-31) | 16185 <1> ; |-------------------------------------------| 16186 <1> ; | 64 bit file offset pointer (bit 32-47) | 16187 <1> ; |-------------------------------------------| 16188 <1> ; | 64 bit file offset pointer (bit 48-63) | 16189 <1> ; |-------------------------------------------| 16190 <1> ; 2 | | 16191 <1> ; |-------------------------------------------| 16192 <1> ; | | 16193 <1> ; |-------------------------------------------| 16194 <1> ; | | 16195 <1> ; |-------------------------------------------| 16196 <1> ; | | 16197 <1> ; |-------------------------------------------| 16198 <1> ; | | 16199 <1> 16200 <1> ; 16201 <1> ; 'fsp' table (10 bytes/entry) 16202 <1> ; bit 15 bit 0 16203 <1> ; ---|------------------------------------------- 16204 <1> ; r/w| i-number of open file 16205 <1> ; ---|------------------------------------------- 16206 <1> ; device number 16207 <1> ; ----------------------------------------------- 16208 <1> ; offset pointer, r/w pointer to file (bit 0-15) 16209 <1> ; ----------------------------------------------- 16210 <1> ; offset pointer, r/w pointer to file (bit 16-31) 16211 <1> ; ----------------------|------------------------ 16212 <1> ; flag that says file | number of processes 16213 <1> ; has been deleted | that have file open 16214 <1> ; ----------------------|------------------------ 16215 <1> ; 16216 <1> 16217 <1> ; 12/03/2022 16218 <1> ; 11/02/2022 16219 <1> ; 01/01/2022 16220 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 16221 <1> syscreat: ; < create file > 16222 <1> ; 12/03/2022 16223 <1> ; 11/02/2022 16224 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 16225 <1> ; 04/04/2021 16226 <1> ; 27/03/2021 (Retro UNIX 386 v2 - Beginning) 16227 <1> ; 27/12/2015 (Retro UNIX 386 v1.1) 16228 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 16229 <1> ; 27/05/2013 (Retro UNIX 8086 v1) 16230 <1> ; 16231 <1> ; 'syscreat' called with two arguments; name and mode. 16232 <1> ; u.namep points to name of the file and mode is put 16233 <1> ; on the stack. 'namei' is called to get i-number of the file. 16234 <1> ; If the file aready exists, it's mode and owner remain 16235 <1> ; unchanged, but it is truncated to zero length. If the file 16236 <1> ; did not exist, an i-node is created with the new mode via 16237 <1> ; 'maknod' whether or not the file already existed, it is 16238 <1> ; open for writing. The fsp table is then searched for a free 16239 <1> ; entry. When a free entry is found, proper data is placed 16240 <1> ; in it and the number of this entry is put in the u.fp list. 16241 <1> ; The index to the u.fp (also know as the file descriptor) 16242 <1> ; is put in the user's r0. 16243 <1> ; 16244 <1> ; Calling sequence: 16245 <1> ; syscreate; name; mode 16246 <1> ; Arguments: 16247 <1> ; name - name of the file to be created 16248 <1> ; mode - mode of the file to be created 16249 <1> ; Inputs: (arguments) 16250 <1> ; Outputs: *u.r0 - index to u.fp list 16251 <1> ; (the file descriptor of new file) 16252 <1> ; ............................................................... 16253 <1> ; 16254 <1> ; Retro UNIX 8086 v1 modification: 16255 <1> ; 'syscreate' system call has two arguments; so, 16256 <1> ; * 1st argument, name is pointed to by BX register 16257 <1> ; * 2nd argument, mode is in CX register 16258 <1> ; 16259 <1> ; AX register (will be restored via 'u.r0') will return 16260 <1> ; to the user with the file descriptor/number 16261 <1> ; (index to u.fp list). 16262 <1> ; 16263 <1> ;call arg2 16264 <1> ; * name - 'u.namep' points to address of file/path name 16265 <1> ; in the user's program segment ('u.segmnt') 16266 <1> ; with offset in BX register (as sysopen argument 1). 16267 <1> ; * mode - sysopen argument 2 is in CX register 16268 <1> ; which is on top of stack. 16269 <1> ; 16270 <1> ; jsr r0,arg2 / put file name in u.namep put mode 16271 <1> ; / on stack 16272 000035C1 891D[C06C0000] <1> mov [u.namep], ebx ; file name address 16273 <1> ;push cx ; mode 16274 <1> ; 04/12/2021 16275 000035C7 51 <1> push ecx ; cx = mode (permission flags) 16276 000035C8 E8AF0A0000 <1> call namei 16277 <1> ; jsr r0,namei / get the i-number 16278 <1> ;and ax, ax 16279 <1> ;jz short syscreat_1 16280 000035CD 7216 <1> jc short syscreat_1 16281 <1> ; br 2f / if file doesn't exist 2f 16282 <1> ; 27/12/2015 16283 <1> ;cmp ax, 41 ; device inode ? 16284 <1> ;jb syscreat_0 ; yes 16285 <1> ; 16286 <1> ;neg ax 16287 <1> ; ; neg r1 / if file already exists make i-number 16288 <1> ; / negative (open for writing) 16289 <1> ; 11/02/2022 16290 <1> ; Truncate existing file 16291 <1> ;syscreate_2: 16292 <1> ;; 27/03/2021 16293 <1> ;;xor edx, edx ; 0 16294 <1> ;;inc dl ; DL = 1 ; create/truncate (open for write) 16295 <1> ;mov dl, 1 16296 <1> ; 11/02/2022 16297 000035CF B202 <1> mov dl, 2 ; create file (call from syscreat) 16298 000035D1 E810200000 <1> call iopen 16299 <1> ; jsr r0,iopen 16300 <1> ; 11/02/2022 16301 <1> ; cpu will return here if inode in eax is regular file inode 16302 <1> ; (if it is device or dir inode, cpu will jumpt to 'error') 16303 <1> ; 16304 <1> ; 12/03/2022 16305 000035D6 50 <1> push eax ; * ; save inode number 16306 <1> ; 16307 <1> ; truncate file to zero length 16308 <1> ;call itrunc 16309 <1> ; jsr r0,itrunc / truncate to 0 length 16310 <1> ; 11/02/2022 16311 <1> ; (iget and regular file check -in 'itrunc'- is not needed) 16312 000035D7 E891170000 <1> call itrunc_1 16313 <1> ; 12/03/2022 16314 000035DC 58 <1> pop eax ; * ; restore inode number in eax 16315 <1> ; 16316 <1> ;pop cx ; pop mode (did not exist in original Unix v1 !?) 16317 <1> ; 04/12/2021 16318 000035DD 59 <1> pop ecx 16319 <1> syscreat_2: 16320 000035DE B201 <1> mov dl, 1 ; open for writing 16321 000035E0 E962FFFFFF <1> jmp sysopen_1 16322 <1> ; br op0 16323 <1> syscreat_1: ; 2: / file doesn't exist 16324 <1> ;pop ax 16325 <1> ; ; mov (sp)+,r1 / put the mode in r1 16326 <1> ; 27/03/2021 16327 000035E5 58 <1> pop eax ; ax = mode (permission flags) 16328 <1> ;xor ah, ah 16329 <1> ; ; bic $!377,r1 / clear upper byte 16330 <1> ; 27/03/2021 16331 <1> ;(ref: Retro UNIX 386 v2 inode flags,'ux.s') 16332 <1> ; clear bits 15,14,13,12,9 of mode (input from user) 16333 000035E6 80E40D <1> and ah, 0Dh ; ISUID (800h) & ISGID (400h) & IREAD (100h) 16334 <1> ; 11/02/2022 16335 000035E9 80CC80 <1> or ah, 80h ; IFREG (8000h) ; Regular file 16336 000035EC E8B40D0000 <1> call maknod 16337 <1> ; jsr r0,maknod / make an i-node for this file 16338 <1> ;sub eax, eax ; 04/12/2021 16339 000035F1 66A1[DC6C0000] <1> mov ax, [u.dirbuf] 16340 <1> ; mov u.dirbuf,r1 / put i-number 16341 <1> ; / for this new file in r1 16342 <1> ; 04/04/2021 16343 <1> ;mov dl, 1 ; open for writing 16344 <1> ; 16345 <1> ;jmp sysopen_1 16346 <1> ; ; br op0 / open the file 16347 <1> ; 04/04/2021 16348 000035F7 EBE5 <1> jmp short syscreat_2 16349 <1> 16350 <1> ; 11/02/2022 16351 <1> ; 04/12/2021 16352 <1> dir_access_err: ; 13/03/2022 16353 <1> ; ; 14/05/2015 16354 <1> ; mov dword [u.error], ERR_DIR_ACCESS ; permission denied ! 16355 <1> ;f_create_error: 16356 <1> ; 27/03/2021 16357 000035F9 C705[186D0000]0B00- <1> mov dword [u.error], ERR_PERM_DENIED ; permission denied ! 16358 00003601 0000 <1> 16359 00003603 E95DFBFFFF <1> jmp error 16360 <1> 16361 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 16362 <1> sysmkdir: ; < make directory > 16363 <1> ; 13/03/2022 16364 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 16365 <1> ; 02/04/2021 16366 <1> ; 27/03/2021 (Retro UNIX 386 v2 - Beginning) 16367 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 16368 <1> ; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 16369 <1> ; 16370 <1> ; 'sysmkdir' creates an empty directory whose name is 16371 <1> ; pointed to by arg 1. The mode of the directory is arg 2. 16372 <1> ; The special entries '.' and '..' are not present. 16373 <1> ; Errors are indicated if the directory already exists or 16374 <1> ; user is not the super user. 16375 <1> ; 16376 <1> ; Calling sequence: 16377 <1> ; sysmkdir; name; mode 16378 <1> ; Arguments: 16379 <1> ; name - points to the name of the directory 16380 <1> ; mode - mode of the directory 16381 <1> ; Inputs: (arguments) 16382 <1> ; Outputs: - 16383 <1> ; (sets 'directory' flag to 1; 16384 <1> ; 'set user id on execution' and 'executable' flags to 0) 16385 <1> ; ............................................................... 16386 <1> ; 16387 <1> ; Retro UNIX 8086 v1 modification: 16388 <1> ; 'sysmkdir' system call has two arguments; so, 16389 <1> ; * 1st argument, name is pointed to by BX register 16390 <1> ; * 2nd argument, mode is in CX register 16391 <1> ; 16392 <1> 16393 <1> ; / make a directory 16394 <1> 16395 <1> ;call arg2 16396 <1> ; * name - 'u.namep' points to address of file/path name 16397 <1> ; in the user's program segment ('u.segmnt') 16398 <1> ; with offset in BX register (as sysopen argument 1). 16399 <1> ; * mode - sysopen argument 2 is in CX register 16400 <1> ; which is on top of stack. 16401 <1> 16402 <1> ; jsr r0,arg2 / put file name in u.namep put mode 16403 <1> ; / on stack 16404 00003608 891D[C06C0000] <1> mov [u.namep], ebx 16405 <1> ;push cx ; mode 16406 <1> ; 27/03/2021 16407 0000360E 51 <1> push ecx ; cx = mode 16408 0000360F E8680A0000 <1> call namei 16409 <1> ; jsr r0,namei / get the i-number 16410 <1> ; br .+4 / if file not found branch around error 16411 <1> ;xor ax, ax 16412 <1> ;jnz error 16413 00003614 7334 <1> jnc short dir_exists ; 14/05/2015 16414 <1> ;jnc error 16415 <1> ; br error2 / directory already exists (error) 16416 <1> 16417 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 16418 <1> ; ;tstb u.uid / is user the super user 16419 <1> ;jna short dir_access_err ; 14/05/2015 16420 <1> ;;jna error 16421 <1> ; ;bne error2 / no, not allowed 16422 <1> ;pop ax 16423 <1> ; ;mov (sp)+,r1 / put the mode in r1 16424 <1> ;and ax, 0FFCFh ; 1111111111001111b 16425 <1> ; ;bic $!317,r1 / all but su and ex 16426 <1> ;;or ax, 4000h ; 1011111111111111b 16427 <1> ;or ah, 40h ; Set bit 14 to 1 16428 <1> ; ;bis $40000,r1 / directory flag 16429 <1> 16430 <1> ; 02/04/2021 16431 <1> ;cmp word [u.uid], 0 16432 <1> ;;ja error 16433 <1> ;ja short dir_access_err 16434 <1> 16435 <1> ; 13/03/2022 16436 <1> ; NOTE: 16437 <1> ; Unix v5-v7 kernels do not allow (ordinary) users 16438 <1> ; (except root/superuser) --if [u.uid] > 0-- 16439 <1> ; to make a sub directory. (ref: sys2.c, 'mknod') 16440 <1> ; 16441 <1> ; But, Retro UNIX 386 v1.2 will allow the owner of 16442 <1> ; the parent directory to make a sub directory, here. 16443 <1> 16444 <1> ; 13/03/2022 16445 00003616 66833D[F66C0000]00 <1> cmp word [u.uid], 0 16446 0000361E 7618 <1> jna short sysmkdir1 ; root (superuser) 16447 <1> 16448 <1> ; Here.. 16449 <1> ; (current) inode buffer contains inode structure 16450 <1> ; of the parent directory (at the return of 'namei'). 16451 <1> 16452 00003620 66A1[28680000] <1> mov ax, [i.uid] ; owner ID of the parent dir 16453 00003626 663B05[F66C0000] <1> cmp ax, [u.uid] ; user ID of current user/process 16454 0000362D 75CA <1> jne short dir_access_err 16455 <1> ; 13/03/2022 16456 <1> ; additional checking (may or may not be necessary!?) 16457 0000362F 663B05[F86C0000] <1> cmp ax, [u.ruid] 16458 <1> ; real (login) user ID must be same 16459 00003636 75C1 <1> jne short dir_access_err 16460 <1> 16461 <1> ; 02/04/2021 16462 <1> ; ('mkdir' procedure will be called from 'maknod' 16463 <1> ; and then 'mkdir' will check write access permission) 16464 <1> ; ((so, 'access_w' call is not needed here.)) 16465 <1> 16466 <1> ;; 02/04/2021 16467 <1> ;; ('make directory' user permission check) 16468 <1> ;; ((current directory's write permission flags 16469 <1> ;; will be checked against user's 'uid' & gid')) 16470 <1> ;mov dx, 80h ; IWRITE 16471 <1> ;call access_w ; (in 'access', 'u5.s') 16472 <1> ;; (If cpu will return here, the user has write permission) 16473 <1> 16474 <1> sysmkdir1: 16475 <1> ; 27/03/2021 16476 00003638 58 <1> pop eax ; ax = mode 16477 <1> ; [ii] = current directory's inode number 16478 <1> 16479 <1> ; 27/03/2021 16480 <1> ;(ref: Retro UNIX 386 v2 inode flags,'ux.s') 16481 <1> ; clear bits 13,12,11,10,9,6,3,0 of mode (input from user) 16482 <1> ;and ax, 0C1B6h ; bits 15,14,8,7,5,4,2,1 16483 00003639 6625B601 <1> and ax, 01B6h 16484 0000363D 80CCC0 <1> or ah, 0C0h ; IFREG (8000h) + IFDIR (4000h) 16485 <1> ; Directory 16486 00003640 E8600D0000 <1> call maknod 16487 <1> ;jsr r0,maknod / make the i-node for the directory 16488 00003645 E93BFBFFFF <1> jmp sysret 16489 <1> ;br sysret2 / 16490 <1> dir_exists: 16491 <1> ; 27/03/2021 16492 <1> ; (same error number for files and directories) 16493 <1> ; Error Number: 14 (ERR_DIR_EXISTS) 16494 0000364A C705[186D0000]0E00- <1> mov dword [u.error], ERR_FILE_EXISTS 16495 00003652 0000 <1> 16496 <1> ; 'file already exists !' error 16497 <1> ; 04/12/2021 16498 00003654 E90CFBFFFF <1> jmp error 16499 <1> ;dir_access_err: 16500 <1> ; ; 14/05/2015 16501 <1> ; mov dword [u.error], ERR_DIR_ACCESS ; permission denied ! 16502 <1> ; jmp error 16503 <1> 16504 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 16505 <1> sysclose: ; 16506 <1> ; 02/03/2022 16507 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 16508 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 16509 <1> ; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1) 16510 <1> ; 16511 <1> ; 'sysclose', given a file descriptor in 'u.r0', closes the 16512 <1> ; associated file. The file descriptor (index to 'u.fp' list) 16513 <1> ; is put in r1 and 'fclose' is called. 16514 <1> ; 16515 <1> ; Calling sequence: 16516 <1> ; sysclose 16517 <1> ; Arguments: 16518 <1> ; - 16519 <1> ; Inputs: *u.r0 - file descriptor 16520 <1> ; Outputs: - 16521 <1> ; ............................................................... 16522 <1> ; 16523 <1> ; Retro UNIX 8086 v1 modification: 16524 <1> ; The user/application program puts file descriptor 16525 <1> ; in BX register as 'sysclose' system call argument. 16526 <1> ; (argument transfer method 1) 16527 <1> 16528 <1> ; / close the file 16529 <1> 16530 <1> ;mov eax, ebx 16531 <1> ; 04/12/2021 16532 <1> ; ebx = file descriptor/number 16533 <1> ;call fclose 16534 <1> ; 02/03/2022 16535 00003659 E8A2090000 <1> call _fclose 16536 <1> ; mov *u.r0,r1 / move index to u.fp list into r1 16537 <1> ; jsr r0,fclose / close the file 16538 <1> ; br error2 / unknown file descriptor 16539 <1> ; br sysret2 16540 <1> ;; 14/05/2015 16541 <1> ;jnc sysret 16542 <1> ; 04/12/2021 16543 0000365E 7205 <1> jc short sysclose_err 16544 00003660 E920FBFFFF <1> jmp sysret 16545 <1> sysclose_err: 16546 00003665 C705[186D0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 16547 0000366D 0000 <1> 16548 0000366F E9F1FAFFFF <1> jmp error 16549 <1> 16550 <1> ; 23/02/2022 16551 <1> ; 19/12/2021 16552 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 16553 <1> sysemt: 16554 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 16555 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 16556 <1> ; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1) 16557 <1> ; 16558 <1> ; Retro UNIX 8086 v1 modification: 16559 <1> ; 'Enable Multi Tasking' system call instead 16560 <1> ; of 'Emulator Trap' in original UNIX v1 for PDP-11. 16561 <1> ; 16562 <1> ; Retro UNIX 8086 v1 feature only! 16563 <1> ; Using purpose: Kernel will start without time-out 16564 <1> ; (internal clock/timer) functionality. 16565 <1> ; Then etc/init will enable clock/timer for 16566 <1> ; multi tasking. (Then it will not be disabled again 16567 <1> ; except hardware reset/restart.) 16568 <1> ; 16569 <1> 16570 <1> ;cmp byte [u.uid], 0 ; root ? 16571 <1> ;;ja error 16572 <1> ;ja badsys ; 14/05/2015 16573 <1> ; 04/12/2021 16574 00003674 66833D[F66C0000]00 <1> cmp word [u.uid], 0 ; root ? 16575 0000367C 7605 <1> jna short emt_0 16576 0000367E E994FBFFFF <1> jmp badsys 16577 <1> emt_0: 16578 00003683 FA <1> cli ; 23/02/2022 16579 00003684 21DB <1> and ebx, ebx 16580 00003686 7429 <1> jz short emt_2 16581 <1> ; Enable multi tasking -time sharing- 16582 00003688 B8[16470000] <1> mov eax, clock ; enable multi tasking clock/timer 16583 <1> ; 23/02/2022 16584 0000368D BA[440A0000] <1> mov edx, rtci_default ; disable rtc (digital) printing 16585 <1> emt_1: 16586 00003692 A3[09070000] <1> mov [x_timer], eax 16587 <1> ; 23/02/2022 (Temporary) 16588 00003697 8915[0D070000] <1> mov [x_rtci], edx 16589 0000369D B306 <1> mov bl, 6 ; timer interrupt page, video page 6 16590 0000369F E855020000 <1> call wttyc ; clear video page 16591 000036A4 B307 <1> mov bl, 7 ; rtc interrupt page, video page 7 16592 000036A6 E84E020000 <1> call wttyc ; clear video page 16593 <1> ; 16594 000036AB FB <1> sti ; 23/02/2022 16595 000036AC E9D4FAFFFF <1> jmp sysret 16596 <1> emt_2: 16597 <1> ; Disable multi tasking -time sharing- 16598 000036B1 B8[15070000] <1> mov eax, u_timer ; enable timer tick printing 16599 <1> ; 23/02/2022 16600 000036B6 BA[4B0A0000] <1> mov edx, rtc_p ; enable rtc (digital) printing 16601 <1> ; 16602 000036BB EBD5 <1> jmp short emt_1 16603 <1> 16604 <1> ; Original UNIX v1 'sysemt' routine 16605 <1> ;sysemt: 16606 <1> ; 16607 <1> ;jsr r0,arg; 30 / put the argument of the sysemt call 16608 <1> ; / in loc 30 16609 <1> ;cmp 30,$core / was the argument a lower address 16610 <1> ; / than core 16611 <1> ;blo 1f / yes, rtssym 16612 <1> ;cmp 30,$ecore / no, was it higher than "core" 16613 <1> ; / and less than "ecore" 16614 <1> ;blo 2f / yes, sysret2 16615 <1> ;1: 16616 <1> ;mov $rtssym,30 16617 <1> ;2: 16618 <1> ;br sysret2 16619 <1> 16620 <1> sysilgins: 16621 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 16622 <1> ; 03/06/2013 16623 <1> ; Retro UNIX 8086 v1 modification: 16624 <1> ; not a valid system call ! (not in use) 16625 <1> ; 16626 000036BD E955FBFFFF <1> jmp badsys 16627 <1> ;jmp error 16628 <1> ;;jmp sysret 16629 <1> 16630 <1> ; Original UNIX v1 'sysemt' routine 16631 <1> ;sysilgins: / calculate proper illegal instruction trap address 16632 <1> ;jsr r0,arg; 10 / take address from sysilgins call 16633 <1> ;/ put it in loc 8., 16634 <1> ;cmp 10,$core / making it the illegal instruction 16635 <1> ; / trap address 16636 <1> ;blo 1f / is the address a user core address? 16637 <1> ; / yes, go to 2f 16638 <1> ;cmp 10,$ecore 16639 <1> ;blo 2f 16640 <1> ;1: 16641 <1> ;mov $fpsym,10 / no, make 'fpsum' the illegal 16642 <1> ; / instruction trap address for the system 16643 <1> ;2: 16644 <1> ;br sysret2 / return to the caller via 'sysret' 16645 <1> 16646 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 16647 <1> sysmdate: ; < change the modification time of a file > 16648 <1> ; 23/02/2022 (Retro UNIX 386 v1 feature/modification) 16649 <1> ; (ECX input) 16650 <1> ; 24/12/2021 16651 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 16652 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 16653 <1> ; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 16654 <1> ; 16655 <1> ; 'sysmdate' is given a file name. It gets inode of this 16656 <1> ; file into core. The user is checked if he is the owner 16657 <1> ; or super user. If he is neither an error occurs. 16658 <1> ; 'setimod' is then called to set the i-node modification 16659 <1> ; byte and the modification time, but the modification time 16660 <1> ; is overwritten by whatever get put on the stack during 16661 <1> ; a 'systime' system call. This calls are restricted to 16662 <1> ; the super user. 16663 <1> ; 16664 <1> ; Calling sequence: 16665 <1> ; sysmdate; name 16666 <1> ; Arguments: 16667 <1> ; name - points to the name of file 16668 <1> ; Inputs: (arguments) 16669 <1> ; Outputs: - 16670 <1> ; ............................................................... 16671 <1> ; 16672 <1> ; Retro UNIX 8086 v1 modification: 16673 <1> ; The user/application program puts address 16674 <1> ; of the file name in BX register 16675 <1> ; as 'sysmdate' system call argument. 16676 <1> ; 16677 <1> ; / change the modification time of a file 16678 <1> ; jsr r0,arg; u.namep / point u.namep to the file name 16679 000036C2 891D[C06C0000] <1> mov [u.namep], ebx 16680 <1> ; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code) 16681 000036C8 890D[B0670000] <1> mov [p_time], ecx ; save new modification time to be set 16682 000036CE E8A9090000 <1> call namei 16683 <1> ; jsr r0,namei / get its i-number 16684 <1> ;;jc error 16685 <1> ; ; br error2 / no, such file 16686 <1> ;jc fnotfound ; file not found ! 16687 <1> ; 24/12/2021 16688 000036D3 7305 <1> jnc short mdate_0 16689 000036D5 E98FFEFFFF <1> jmp fnotfound 16690 <1> mdate_0: 16691 000036DA E896140000 <1> call iget 16692 <1> ; jsr r0,iget / get i-node into core 16693 <1> ;mov al, [u.uid] 16694 <1> ;cmp al, [i.uid] 16695 <1> ; ; cmpb u.uid,i.uid / is user same as owner 16696 <1> ;je short mdate_1 16697 <1> ; ; beq 1f / yes 16698 <1> ;and al, al 16699 <1> ; ; tstb u.uid / no, is user the super user 16700 <1> ;;jnz error 16701 <1> ; ; bne error2 / no, error 16702 <1> ;jz short mdate_1 16703 <1> ; 04/12/2021 16704 000036DF 66A1[F66C0000] <1> mov ax, [u.uid] 16705 000036E5 663B05[28680000] <1> cmp ax, [i.uid] 16706 000036EC 7414 <1> je short mdate_1 16707 000036EE 6621C0 <1> and ax, ax 16708 000036F1 740F <1> jz short mdate_1 16709 <1> 16710 000036F3 C705[186D0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 16711 000036FB 0000 <1> 16712 <1> sysstty_err: ; 06/02/2022 16713 000036FD E963FAFFFF <1> jmp error 16714 <1> mdate_1: ;1: 16715 00003702 E8FF150000 <1> call setimod 16716 <1> ; jsr r0,setimod / fill in modification data, 16717 <1> ; / time etc. 16718 00003707 BE[B0670000] <1> mov esi, p_time 16719 0000370C BF[5C680000] <1> mov edi, i.mtim 16720 00003711 A5 <1> movsd 16721 <1> ; mov 4(sp),i.mtim / move present time to 16722 <1> ; mov 2(sp),i.mtim+2 / modification time 16723 00003712 E96EFAFFFF <1> jmp sysret 16724 <1> ; br sysret2 16725 <1> 16726 <1> ; 06/02/2022 16727 <1> sysstty_err_s: 16728 00003717 880D[A46C0000] <1> mov byte [u.r0], cl ; serial port's tty number 16729 0000371D EBDE <1> jmp short sysstty_err 16730 <1> 16731 <1> sysstty: ; < set tty status and mode > 16732 <1> ; 22/02/2022 16733 <1> ; 21/02/2022 16734 <1> ; 06/02/2022 (Retro UNIX 286 v1.2) 16735 <1> ; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 16736 <1> ; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 16737 <1> ; 01/02/2022 (Retro UNIX 386 v1) -clear screen- 16738 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 16739 <1> ; ((32 bit reg push/pop)) 16740 <1> ; 17/11/2015 16741 <1> ; 12/11/2015 16742 <1> ; 29/10/2015 16743 <1> ; 17/10/2015 16744 <1> ; 13/10/2015 16745 <1> ; 29/06/2015 16746 <1> ; 27/06/2015 (Retro UNIX 386 v1 - Beginning) 16747 <1> ; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1) 16748 <1> ; 16749 <1> ; 'sysstty' sets the status and mode of the typewriter 16750 <1> ; whose file descriptor is in (u.r0). 16751 <1> ; 16752 <1> ; Calling sequence: 16753 <1> ; sysstty; arg 16754 <1> ; Arguments: 16755 <1> ; arg - address of 3 consequitive words that contain 16756 <1> ; the source of status data 16757 <1> ; Inputs: ((*u.r0 - file descriptor & argument)) 16758 <1> ; Outputs: ((status in address which is pointed to by arg)) 16759 <1> ; ............................................................... 16760 <1> ; 16761 <1> ; Retro UNIX 8086 v1 modification: 16762 <1> ; 'sysstty' system call will set the tty 16763 <1> ; (clear keyboard buffer and set cursor position) 16764 <1> ; in following manner: 16765 <1> ; NOTE: All of tty setting functions are here (16/01/2014) 16766 <1> ; 16767 <1> ; Inputs: 16768 <1> ; BX = 0 --> means 16769 <1> ; If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022 16770 <1> ; set cursor position for console tty, only 16771 <1> ; CH will be ignored (char. will not be written) 16772 <1> ; If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222 16773 <1> ; set console tty for (current) process 16774 <1> ; CL = tty number (0 to 9) 16775 <1> ; (If CH = 0, character will not be written) 16776 <1> ; If CH > 0 (CL < FFh) 16777 <1> ; CL = tty number (0 to 9) 16778 <1> ; CH = character will be written 16779 <1> ; at requested cursor position (in DX) 16780 <1> ; DX = cursor position for tty number 0 to 7. 16781 <1> ; (only tty number 0 to 7) 16782 <1> ; DL = communication parameters (for serial ports) 16783 <1> ; (only for COM1 and COM2 serial ports) 16784 <1> ; DH < 0FFh -> DL is valid, initialize serial port 16785 <1> ; or set cursor position 16786 <1> ; DH = 0FFh -> DL is not valid 16787 <1> ; do not set serial port parameters 16788 <1> ; or do not set cursor position 16789 <1> ; 16790 <1> ; BX > 0 --> points to name of tty 16791 <1> ; CH > 0 --> 16792 <1> ; CH = character will be written in current 16793 <1> ; cursor position (for tty number from 0 to 7) 16794 <1> ; or character will be sent to serial port 16795 <1> ; (for tty number 8 or 9) 16796 <1> ; CL = color of the character if tty number < 8. 16797 <1> ; CH = 0 --> Do not write a character, 16798 <1> ; set mode (tty 8 to 9) or 16799 <1> ; set current cursor positions (tty 0 to 7) only. 16800 <1> ; DX = cursor position for tty number 0 to 7. 16801 <1> ; DH = FFh --> Do not set cursor pos (or comm. params.) 16802 <1> ; (DL is not valid) 16803 <1> ; DL = communication parameters 16804 <1> ; for tty number 8 or 9 (COM1 or COM2). 16805 <1> ; 16806 <1> ; 01/02/2022 - Retro UNIX 386 v1 - 2022 modification 16807 <1> ; (30/01/2022 - Retro UNIX 8086 - 2022 modification) 16808 <1> ; If CH = 0 & DX = 0FFFFh -> 16809 <1> ; clear screen (video page) & set cursor pos to 0,0. 16810 <1> ; (for tty number 0 to 7, CL <= 7) 16811 <1> ; (if CL = 0FFh -> clear console tty) 16812 <1> ; 16813 <1> ; Outputs: 16814 <1> ; cf = 0 -> OK 16815 <1> ; AL = tty number (0 to 9) 16816 <1> ; AH = line status if tty number is 8 or 9 16817 <1> ; AH = process number (of the caller) 16818 <1> ; cf = 1 means error (requested tty is not ready) 16819 <1> ; AH = FFh if the tty is locked 16820 <1> ; (owned by another process) 16821 <1> ; = process number (of the caller) 16822 <1> ; (if < FFh and tty number < 8) 16823 <1> ; AL = tty number (0FFh if it does not exist) 16824 <1> ; AH = line status if tty number is 8 or 9 16825 <1> ; NOTE: Video page will be cleared if cf = 0. 16826 <1> ; 16827 <1> 16828 <1> ; 27/06/2015 (32 bit modifications) 16829 <1> ; 14/01/2014 16830 0000371F 31C0 <1> xor eax, eax 16831 00003721 6648 <1> dec ax ; 17/10/2015 16832 00003723 A3[A46C0000] <1> mov [u.r0], eax ; 0FFFFh 16833 <1> ;;; 16834 <1> ; 01/02/2022 16835 00003728 FEC1 <1> inc cl ; 0FFh -> 0, 7 -> 8 16836 0000372A 39C2 <1> cmp edx, eax 16837 <1> ;cmp dx, ax ; 0FFFFh 16838 0000372C 7521 <1> jne short sysstty_18 16839 <1> ; clear video page 16840 <1> ; (CH must be 0) 16841 0000372E 08ED <1> or ch, ch 16842 00003730 75CB <1> jnz short sysstty_err ; invalid parameters 16843 00003732 80F908 <1> cmp cl, 8 ; > tty7 (serial port?) 16844 00003735 77C6 <1> ja short sysstty_err ; invalid parameters 16845 00003737 20C9 <1> and cl, cl 16846 00003739 7514 <1> jnz short sysstty_18 ; actual tty (video page) num + 1 16847 0000373B 0FB635[F56C0000] <1> movzx esi, byte [u.uno] 16848 00003742 8A8E[A3680000] <1> mov cl, byte [esi+p.ttyc-1] ; current/console tty 16849 00003748 80F907 <1> cmp cl, 7 16850 0000374B 77CA <1> ja short sysstty_err_s ; serial port ! 16851 <1> ; here CL contains (actual) tty number (tty0 to tty7) 16852 0000374D FEC1 <1> inc cl ; 0 -> 1, 7 -> 8 16853 <1> sysstty_18: 16854 0000374F FEC9 <1> dec cl ; 8 -> 7, 1 -> 0 16855 <1> ; cl = video page (tty) number 16856 <1> ;;; 16857 00003751 21DB <1> and ebx, ebx 16858 <1> ;jnz sysstty_6 16859 <1> ; 01/02/2022 16860 00003753 7405 <1> jz short sysstty_19 16861 00003755 E9C2000000 <1> jmp sysstty_6 16862 <1> sysstty_19: 16863 <1> ; set console tty 16864 <1> ; 29/10/2015 16865 <1> ; 17/01/2014 16866 0000375A 80F909 <1> cmp cl, 9 16867 0000375D 7613 <1> jna short sysstty_0 16868 <1> ; 17/11/2015 16869 0000375F 80F9FF <1> cmp cl, 0FFh 16870 00003762 7202 <1> jb short sysstty_13 16871 00003764 88CD <1> mov ch, cl ; force CH value to FFh 16872 <1> sysstty_13: 16873 00003766 8A1D[F56C0000] <1> mov bl, [u.uno] ; process number 16874 0000376C 8A8B[A3680000] <1> mov cl, [ebx+p.ttyc-1] ; current/console tty 16875 <1> sysstty_0: 16876 <1> ; 29/06/2015 16877 00003772 52 <1> push edx ; 24/12/2021 16878 00003773 51 <1> push ecx 16879 00003774 30D2 <1> xor dl, dl ; sysstty call sign 16880 00003776 88C8 <1> mov al, cl 16881 00003778 A2[A46C0000] <1> mov [u.r0], al ; tty number (0 to 9) 16882 0000377D E8311F0000 <1> call ottyp 16883 00003782 59 <1> pop ecx 16884 00003783 5A <1> pop edx 16885 <1> ; 16886 00003784 7220 <1> jc short sysstty_pd_err 16887 <1> ; 16888 <1> ; 22/02/2022 (Bug!, BugFix) 16889 <1> ; (ebx = ?, modified in ottyp, it may be > 255) 16890 <1> ; 16891 00003786 80F908 <1> cmp cl, 8 16892 00003789 720C <1> jb short sysstty_2 16893 <1> ; 16894 0000378B 80FEFF <1> cmp dh, 0FFh 16895 0000378E 7407 <1> je short sysstty_2 16896 <1> 16897 <1> ; 01/02/2022 16898 <1> ; ; 29/10/2015 16899 <1> ; mov ah, dl ; communication parameters 16900 <1> ; ; ah = 0E3h = 11100011b = 115200 baud, 16901 <1> ; ; THRE int + RDA int 16902 <1> ; ; ah = 23h = 00100011b = 9600 baud, 16903 <1> ; ; THRE int + RDA int 16904 <1> ; sub al, al ; 0 16905 <1> ; ; 12/07/2014 16906 <1> ; cmp cl, 9 16907 <1> ; jb short sysstty_1 16908 <1> ; inc al 16909 <1> ;sysstty_1: 16910 <1> ; ; 01/02/2022 16911 <1> ; push ecx 16912 <1> ; ; 29/06/2015 16913 <1> ; call sp_setp ; Set serial port communication parameters 16914 <1> ; mov [u.r0+1], cx ; Line status (ah) 16915 <1> ; ; Modem status (EAX bits 16 to 23) 16916 <1> ; ; 01/02/2022 16917 <1> ; pop ecx 16918 <1> ; jc short sysstty_tmout_err ; 29/10/2015 16919 <1> 16920 <1> ; 01/02/2022 16921 00003790 E831010000 <1> call sysstty_scp 16922 00003795 7276 <1> jc short sysstty_tmout_err ; 29/10/2015 16923 <1> 16924 <1> sysstty_2: 16925 <1> ; 17/01/2014 16926 00003797 20ED <1> and ch, ch ; set cursor position 16927 <1> ; or comm. parameters ONLY 16928 00003799 7527 <1> jnz short sysstty_3 16929 <1> ; 01/02/2022 16930 0000379B 6683FAFF <1> cmp dx, 0FFFFh 16931 0000379F 7214 <1> jb short sysstty_20 16932 <1> ; clear screen (video page) 16933 000037A1 E93C010000 <1> jmp sysstty_14 16934 <1> 16935 <1> sysstty_pd_err: ; 29/06/2015 16936 <1> ; 'permission denied !' error 16937 000037A6 C705[186D0000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER 16938 000037AE 0000 <1> 16939 000037B0 E9B0F9FFFF <1> jmp error 16940 <1> 16941 <1> sysstty_20: 16942 000037B5 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 16943 000037BC 888B[A3680000] <1> mov [ebx+p.ttyc-1], cl ; console tty 16944 <1> sysstty_3: 16945 <1> ; 16/01/2014 16946 000037C2 88E8 <1> mov al, ch ; character ; 0 to FFh 16947 <1> ; 17/11/2015 16948 000037C4 B507 <1> mov ch, 7 ; Default color (light gray) 16949 000037C6 38E9 <1> cmp cl, ch ; 7 (tty number) 16950 <1> ;jna sysstty_9 16951 <1> ; 24/12/2021 16952 000037C8 7705 <1> ja short sysstty_12 16953 000037CA E9C6000000 <1> jmp sysstty_9 16954 <1> 16955 <1> sysstty_12: 16956 <1> ;; BX = 0, CL = 8 or CL = 9 16957 <1> ; (Set specified serial port as console tty port) 16958 <1> ; CH = character to be written 16959 <1> ; 15/04/2014 16960 <1> ; CH = 0 --> initialization only 16961 <1> ; AL = character 16962 <1> ; 26/06/2014 16963 000037CF 880D[D96C0000] <1> mov [u.ttyn], cl 16964 <1> ; 12/07/2014 16965 000037D5 88CC <1> mov ah, cl ; tty number (8 or 9) 16966 <1> ; 02/02/2022 16967 000037D7 FEC0 <1> inc al ; 0FFh -> 0, 0 -> 1 16968 000037D9 740B <1> jz short sysstty_4 ; al = ch = 0 16969 000037DB FEC8 <1> dec al ; 1 -> 0 16970 <1> ;and al, al 16971 000037DD 7407 <1> jz short sysstty_4 ; al = ch = 0 16972 <1> ; 04/07/2014 16973 000037DF E802240000 <1> call sndc 16974 <1> ; 12/07/2014 16975 000037E4 EB0C <1> jmp short sysstty_5 16976 <1> 16977 <1> sysstty_4: 16978 <1> ; 12/07/2014 16979 <1> ;xchg ah, al ; al = 0 -> al = ah, ah = 0 16980 000037E6 88E0 <1> mov al, ah ; 29/06/2015 16981 000037E8 2C08 <1> sub al, 8 16982 <1> ; 27/06/2015 16983 000037EA E8B0F3FFFF <1> call sp_status ; get serial port status 16984 <1> ; AL = Line status, AH = Modem status 16985 <1> ; 12/11/2015 16986 000037EF 3C80 <1> cmp al, 80h 16987 000037F1 F5 <1> cmc 16988 <1> sysstty_5: 16989 000037F2 66A3[A56C0000] <1> mov [u.r0+1], ax ; ah = line status 16990 <1> ; EAX bits 16-23 = modem status 16991 000037F8 9C <1> pushf 16992 000037F9 30D2 <1> xor dl, dl ; sysstty call sign 16993 000037FB A0[D96C0000] <1> mov al, [u.ttyn] ; 26/06/2014 16994 00003800 E8E11F0000 <1> call cttyp 16995 00003805 9D <1> popf 16996 <1> ;jnc sysret ; time out error 16997 <1> ; 01/02/2022 16998 00003806 7205 <1> jc short sysstty_tmout_err 16999 00003808 E978F9FFFF <1> jmp sysret 17000 <1> 17001 <1> ; time out error 17002 <1> sysstty_tmout_err: 17003 0000380D C705[186D0000]1900- <1> mov dword [u.error], ERR_TIME_OUT 17004 00003815 0000 <1> 17005 00003817 E949F9FFFF <1> jmp error 17006 <1> 17007 <1> sysstty_6: 17008 0000381C 52 <1> push edx ; 24/12/2021 17009 0000381D 51 <1> push ecx 17010 0000381E 891D[C06C0000] <1> mov [u.namep], ebx 17011 00003824 E853080000 <1> call namei 17012 00003829 59 <1> pop ecx 17013 0000382A 5A <1> pop edx 17014 0000382B 7259 <1> jc short sysstty_inv_dn 17015 <1> ; 17016 <1> ; 21/02/2022 17017 <1> ;cmp ax, 19 ; inode number of /dev/COM2 17018 <1> ;ja short sysstty_inv_dn ; 27/06/2015 17019 <1> ;; 17020 <1> ;cmp al, 10 ; /dev/tty0 .. /dev/tty7 17021 <1> ; ; /dev/COM1, /dev/COM2 17022 <1> ;jb short sysstty_7 17023 <1> ;sub al, 10 17024 <1> ;jmp short sysstty_8 17025 <1> ; 17026 <1> ; 21/02/2022 17027 <1> ; (Retro UNIX 386 v2 file system inode numbers) 17028 0000382D 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 17029 00003830 7754 <1> ja short sysstty_inv_dn 17030 <1> ;cmp al, 8 ; /dev/tty inode number is 8 17031 <1> ;jb short sysstty_inv_dn 17032 00003832 2C08 <1> sub al, 8 17033 00003834 7250 <1> jb short sysstty_inv_dn 17034 00003836 7408 <1> jz short sysstty_7 ; /dev/tty inode number is 8 17035 <1> ; convert inode number to tty number (tty0 to tty9) 17036 00003838 2C09 <1> sub al, 9 17037 0000383A 724A <1> jb short sysstty_inv_dn 17038 <1> ; al = 0 to 9 17039 0000383C 29DB <1> sub ebx, ebx ; 22/02/2022 17040 0000383E EB0D <1> jmp short sysstty_8 17041 <1> sysstty_7: 17042 <1> ; 21/02/2022 17043 <1> ;cmp al, 1 ; /dev/tty 17044 <1> ;jne short sysstty_inv_dn ; 27/06/2015 17045 00003840 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 17046 00003847 8A83[A3680000] <1> mov al, [ebx+p.ttyc-1] ; console tty 17047 <1> sysstty_8: 17048 <1> ; 22/02/2022 17049 <1> ; (ebx < 256) 17050 0000384D A2[A46C0000] <1> mov [u.r0], al 17051 00003852 52 <1> push edx ; 24/12/2021 17052 00003853 50 <1> push eax 17053 00003854 51 <1> push ecx 17054 00003855 E8591E0000 <1> call ottyp 17055 0000385A 59 <1> pop ecx 17056 0000385B 58 <1> pop eax 17057 0000385C 5A <1> pop edx 17058 <1> ;jc sysstty_pd_err ; 'permission denied !' 17059 <1> ; 06/02/2022 17060 0000385D 7305 <1> jnc short sysstty_21 17061 <1> ; 'permission denied !' 17062 0000385F E942FFFFFF <1> jmp sysstty_pd_err 17063 <1> sysstty_21: 17064 <1> ; 29/10/2015 17065 00003864 86E9 <1> xchg ch, cl 17066 <1> ; cl = character, ch = color code 17067 00003866 86C1 <1> xchg al, cl 17068 <1> ; al = character, cl = tty number 17069 00003868 80F907 <1> cmp cl, 7 17070 <1> ;ja sysstty_12 17071 <1> ; 06/02/2022 17072 0000386B 7628 <1> jna short sysstty_16 17073 <1> ;; 17074 0000386D 80FEFF <1> cmp dh, 0FFh 17075 00003870 740B <1> je short sysstty_22 ; do not set comm. parameters 17076 <1> 17077 <1> ; 01/02/2022 17078 <1> ; ; 29/10/2015 17079 <1> ; mov ah, dl ; communication parameters 17080 <1> ; ; ah = 0E3h = 11100011b = 115200 baud, 17081 <1> ; ; THRE int + RDA int 17082 <1> ; ; ah = 23h = 00100011b = 9600 baud, 17083 <1> ; ; THRE int + RDA int 17084 <1> ; sub al, al ; 0 17085 <1> ; ; 12/07/2014 17086 <1> ; cmp cl, 9 17087 <1> ; jb short sysstty_1 17088 <1> ; inc al 17089 <1> ;sysstty_1: 17090 <1> ; ; 01/02/2022 17091 <1> ; push ecx 17092 <1> ; ; 29/06/2015 17093 <1> ; call sp_setp ; Set serial port communication parameters 17094 <1> ; mov [u.r0+1], cx ; Line status (ah) 17095 <1> ; ; Modem status (EAX bits 16 to 23) 17096 <1> ; ; 01/02/2022 17097 <1> ; pop ecx 17098 <1> ; jc short sysstty_tmout_err ; 29/10/2015 17099 <1> 17100 <1> ; 02/02/2022 17101 00003872 88C5 <1> mov ch, al ; save char 17102 <1> ; 01/02/2022 17103 00003874 E84D000000 <1> call sysstty_scp 17104 00003879 7292 <1> jc short sysstty_tmout_err ; 29/10/2015 17105 <1> ; 02/02/2022 17106 0000387B 88E8 <1> mov al, ch ; restore char 17107 <1> sysstty_22: 17108 <1> ; 01/02/2022 17109 0000387D 08ED <1> or ch, ch 17110 0000387F 7437 <1> jz short sysstty_11 ; do not send char to terminal 17111 <1> ; send char to (serial port) terminal 17112 <1> ; al = character 17113 <1> ; cl = tty number (8 or 9) 17114 00003881 E949FFFFFF <1> jmp sysstty_12 ; (tty8 or tty9) 17115 <1> 17116 <1> sysstty_inv_dn: 17117 <1> ; 27/06/2015 17118 <1> ; Invalid device name (not a tty) ! error 17119 <1> ; (Device is not a tty or device name not found) 17120 00003886 C705[186D0000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 17121 0000388E 0000 <1> 17122 00003890 E9D0F8FFFF <1> jmp error 17123 <1> 17124 <1> sysstty_16: 17125 <1> ; 22/02/2022 17126 <1> ; 16/01/2014 17127 <1> ;xor bh, bh 17128 <1> sysstty_9: ; tty 0 to tty 7 17129 <1> ; al = character 17130 <1> ; ch = color/attribute ; 01/02/2022 17131 <1> ; 17132 <1> ; 22/02/2022 (BugFix) 17133 <1> ; (ebx may be > 255 here!? due to 'ottyp') 17134 00003895 29DB <1> sub ebx, ebx ; * 17135 00003897 88CB <1> mov bl, cl ; (tty number = video page number) 17136 <1> ; 17137 00003899 80FEFF <1> cmp dh, 0FFh ; Do not set cursor position 17138 0000389C 7409 <1> je short sysstty_10 17139 <1> ; 24/12/2021 17140 0000389E 51 <1> push ecx 17141 0000389F 50 <1> push eax 17142 <1> ; 22/02/2022 17143 <1> ;;movzx ebx, cl ; * 17144 <1> ;mov bl, cl ; (tty number = video page number) 17145 000038A0 E819DBFFFF <1> call set_cpos 17146 000038A5 58 <1> pop eax 17147 000038A6 59 <1> pop ecx 17148 <1> sysstty_10: 17149 <1> ; 22/02/2022 17150 <1> ; bl = video page (tty) number 17151 <1> ; 17152 <1> ; 29/10/2015 17153 000038A7 08C0 <1> or al, al ; character 17154 000038A9 740D <1> jz short sysstty_11 ; al = 0 17155 <1> ; 17/11/2015 17156 000038AB 3CFF <1> cmp al, 0FFh 17157 000038AD 7309 <1> jnb short sysstty_11 17158 <1> ; ch > 0 and ch < FFh 17159 <1> ; write a character at current cursor position 17160 000038AF 88EC <1> mov ah, ch ; color/attribute 17161 <1> ; 12/07/2014 17162 000038B1 51 <1> push ecx ; 24/12/2021 17163 000038B2 E8EFDBFFFF <1> call write_c_current 17164 000038B7 59 <1> pop ecx 17165 <1> sysstty_11: 17166 <1> ; 14/01/2014 17167 000038B8 30D2 <1> xor dl, dl ; sysstty call sign 17168 <1> ; 18/01/2014 17169 <1> ;movzx eax, cl ; 27/06/2015 17170 000038BA 88C8 <1> mov al, cl 17171 000038BC E8251F0000 <1> call cttyp 17172 000038C1 E9BFF8FFFF <1> jmp sysret 17173 <1> 17174 <1> ; 06/02/2022 (Retro UNIX 386 v1.2) 17175 <1> sysstty_scp: 17176 <1> ; 02/02/2022 17177 <1> ; set communication parameters (for COM1 or COM2) 17178 <1> ; 01/02/2022 17179 <1> ; 17180 <1> ; 29/10/2015 17181 000038C6 88D4 <1> mov ah, dl ; communication parameters 17182 <1> ; ah = 0E3h = 11100011b = 115200 baud, 17183 <1> ; THRE int + RDA int 17184 <1> ; ah = 23h = 00100011b = 9600 baud, 17185 <1> ; THRE int + RDA int 17186 000038C8 28C0 <1> sub al, al ; 0 17187 <1> ; 12/07/2014 17188 000038CA 80F909 <1> cmp cl, 9 17189 000038CD 7202 <1> jb short sysstty_1 17190 000038CF FEC0 <1> inc al 17191 <1> sysstty_1: 17192 <1> ; 02/02/2022 17193 000038D1 52 <1> push edx 17194 <1> ; 01/02/2022 17195 000038D2 51 <1> push ecx 17196 <1> ; 29/06/2015 17197 000038D3 E8CFF2FFFF <1> call sp_setp ; Set serial port communication parameters 17198 000038D8 66890D[A56C0000] <1> mov [u.r0+1], cx ; Line status (ah) 17199 <1> ; Modem status (EAX bits 16 to 23) 17200 <1> ; 01/02/2022 17201 000038DF 59 <1> pop ecx 17202 000038E0 5A <1> pop edx ; 02/02/2022 17203 <1> ; 01/02/2022 17204 <1> ; if cf = 1 -> sysstty_tmout_err 17205 000038E1 C3 <1> retn 17206 <1> 17207 <1> ; 06/02/2022 (Retro UNIX 386 v1.2) 17208 <1> sysstty_14: 17209 <1> ; 23/02/2022 17210 <1> ; 02/02/2022 17211 <1> ; ch = 0 17212 <1> ; cl = video page 17213 <1> ; 17214 <1> ; dx = 0FFFFh 17215 <1> ; clear screen (video page) 17216 <1> ; 17217 <1> 17218 <1> ; 02/02/2022 17219 <1> ; clear screen 17220 <1> ; 17221 <1> ; (modified registers: eax, ebx, ecx, edx, esi, edi) 17222 <1> 17223 <1> ; 23/02/2022 17224 000038E2 88CB <1> mov bl, cl ; CL = tty number (0 to 7) 17225 <1> 17226 <1> ; clear video page 17227 000038E4 E810000000 <1> call wttyc ; 23/02/2022 17228 <1> 17229 <1> ; 23/02/2022 17230 000038E9 88D8 <1> mov al, bl 17231 000038EB 8A25[F56C0000] <1> mov ah, [u.uno] 17232 000038F1 66A3[A46C0000] <1> mov [u.r0], ax 17233 000038F7 EBBF <1> jmp short sysstty_11 17234 <1> 17235 <1> wttyc: 17236 <1> ; 23/02/2022 17237 <1> ; (clear video page) 17238 <1> ; INPUT: 17239 <1> ; bl = video page (0 to 7) 17240 <1> ; 17241 <1> ; Modified registers: eax, ecx, edx, esi, edi 17242 <1> 17243 <1> ;xor dx, dx ; column 0, row 0 17244 <1> ;;inc dx ; 0 ; 23/02/2022 17245 <1> ; 17246 <1> ; movzx ebx, cl 17247 <1> ; mov bl, cl ; CL = tty number (0 to 7) ; 23/02/2022 17248 <1> 17249 <1> ; shl bl, 1 17250 <1> ; mov al, byte ptr [ebx+ttyl] 17251 <1> ; ; AL = lock value (0 or process number) 17252 <1> ; or al, al 17253 <1> ; jz short @f 17254 <1> ; cmp al, byte ptr [u.uno] ; process number 17255 <1> ; jne short sysstty_15 17256 <1> ; ; only the owner can clear its video page 17257 <1> ; xor al, al ; 0 17258 <1> ;@@: 17259 <1> ; ;mov bl, cl 17260 <1> ; shr bl, 1 17261 <1> 17262 000038F9 30C0 <1> xor al, al ; 0 17263 000038FB B407 <1> mov ah, 07h ; attribute/color (default) 17264 <1> 17265 <1> ; scroll_up input: 17266 <1> ; 17267 <1> ; al = line count (0 or 1) ((0 == clear video page)) 17268 <1> ; ((al = 1 for write_tty (putc) procedure)) 17269 <1> ; ah = attribute to be used on blanked line 17270 <1> ; bl = video page number (0 to 7) 17271 <1> 17272 000038FD E842DBFFFF <1> call scroll_up ; clear video page (al=0) 17273 <1> 17274 <1> ; (modified registers: eax, ecx, edx, esi, edi) 17275 <1> 17276 <1> ; bl = video page number (0 to 7) 17277 <1> ;xor dx, dx ; column 0, row 0 17278 <1> ; 02/02/2022 17279 00003902 31D2 <1> xor edx, edx 17280 <1> ; 23/02/2022 17281 <1> ;call set_cpos 17282 <1> ;retn 17283 00003904 E9B5DAFFFF <1> jmp set_cpos 17284 <1> 17285 <1> ;mov al, bl 17286 <1> ;mov ah, [u.uno] 17287 <1> ;mov [u.r0], ax 17288 <1> ;jmp short sysstty_11 17289 <1> 17290 <1> ;sysstty_15: 17291 <1> ; ; 30/01/2022 17292 <1> ; ; permission (denied) error 17293 <1> ; ;xor dl, dl ; sysstty call sign 17294 <1> ; mov al, cl 17295 <1> ; sub ah, ah ; 0 17296 <1> ; call cttyp 17297 <1> ; jmp error 17298 <1> 17299 <1> ; Original UNIX v1 'sysstty' routine: 17300 <1> ; gtty: 17301 <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments 17302 <1> ;jsr r0,gtty / r1 will have offset to tty block, 17303 <1> ; / r2 has source 17304 <1> ;mov r2,-(sp) 17305 <1> ;mov r1,-(sp) / put r1 and r2 on the stack 17306 <1> ;1: / flush the clist wait till typewriter is quiescent 17307 <1> ;mov (sp),r1 / restore r1 to tty block offset 17308 <1> ;movb tty+3(r1),0f / put cc offset into getc argument 17309 <1> ;mov $240,*$ps / set processor priority to 5 17310 <1> ;jsr r0,getc; 0:../ put character from clist in r1 17311 <1> ; br .+4 / list empty, skip branch 17312 <1> ;br 1b / get another character until list is empty 17313 <1> ;mov 0b,r1 / move cc offset to r1 17314 <1> ;inc r1 / bump it for output clist 17315 <1> ;tstb cc(r1) / is it 0 17316 <1> ;beq 1f / yes, no characters to output 17317 <1> ;mov r1,0f / no, put offset in sleep arg 17318 <1> ;jsr r0,sleep; 0:.. / put tty output process to sleep 17319 <1> ;br 1b / try to calm it down again 17320 <1> ;1: 17321 <1> ;mov (sp)+,r1 17322 <1> ;mov (sp)+,r2 / restore registers 17323 <1> ;mov (r2)+,r3 / put reader control status in r3 17324 <1> ;beq 1f / if 0, 1f 17325 <1> ;mov r3,rcsr(r1) / move r.c. status to reader 17326 <1> ; / control status register 17327 <1> ;1: 17328 <1> ;mov (r2)+,r3 / move pointer control status to r3 17329 <1> ;beq 1f / if 0 1f 17330 <1> ;mov r3,tcsr(r1) / move p.c. status to printer 17331 <1> ; / control status reg 17332 <1> ;1: 17333 <1> ;mov (r2)+,tty+4(r1) / move to flag byte of tty block 17334 <1> ;jmp sysret2 / return to user 17335 <1> 17336 <1> sysgtty: ; < get tty status > 17337 <1> ; 22/02/2022 17338 <1> ; 21/02/2022 17339 <1> ; (Retro UNIX 386 v1.2, inode number modifications) 17340 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 17341 <1> ; ((32 bit reg push/pop)) 17342 <1> ; 23/11/2015 17343 <1> ; 29/10/2015 17344 <1> ; 17/10/2015 17345 <1> ; 28/06/2015 (Retro UNIX 386 v1 - Beginning) 17346 <1> ; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1) 17347 <1> ; 17348 <1> ; 'sysgtty' gets the status of tty in question. 17349 <1> ; It stores in the three words addressed by it's argument 17350 <1> ; the status of the typewriter whose file descriptor 17351 <1> ; in (u.r0). 17352 <1> ; 17353 <1> ; Calling sequence: 17354 <1> ; sysgtty; arg 17355 <1> ; Arguments: 17356 <1> ; arg - address of 3 words destination of the status 17357 <1> ; Inputs: ((*u.r0 - file descriptor)) 17358 <1> ; Outputs: ((status in address which is pointed to by arg)) 17359 <1> ; ............................................................... 17360 <1> ; 17361 <1> ; Retro UNIX 8086 v1 modification: 17362 <1> ; 'sysgtty' system call will return status of tty 17363 <1> ; (keyboard, serial port and video page status) 17364 <1> ; in following manner: 17365 <1> ; 17366 <1> ; Inputs: 17367 <1> ; BX = 0 --> means 17368 <1> ; CH = 0 --> 'return status of the console tty' 17369 <1> ; for (current) process 17370 <1> ; CL = 0 --> return keyboard status (tty 0 to 9) 17371 <1> ; CL = 1 --> return video page status (tty 0 to 7) 17372 <1> ; CL = 1 --> return serial port status (tty 8 & 9) 17373 <1> ; CH > 0 --> tty number + 1 17374 <1> ; 17375 <1> ; BX > 0 --> points to name of tty 17376 <1> ; CL = 0 --> return keyboard status 17377 <1> ; CL = 1 --> return video page status 17378 <1> ; CH = undefined 17379 <1> ; 17380 <1> ; Outputs: 17381 <1> ; cf = 0 -> 17382 <1> ; 17383 <1> ; AL = tty number from 0 to 9 17384 <1> ; (0 to 7 is also the video page of the tty) 17385 <1> ; AH = 0 if the tty is free/unused 17386 <1> ; AH = the process number of the caller 17387 <1> ; AH = FFh if the tty is locked by another process 17388 <1> ; 17389 <1> ; (if calling is for serial port status) 17390 <1> ; BX = serial port status if tty number is 8 or 9 17391 <1> ; (BH = modem status, BL = Line status) 17392 <1> ; CX = 0FFFFh (if data is ready) 17393 <1> ; CX = 0 (if data is not ready or undefined) 17394 <1> ; 17395 <1> ; (if calling is for keyboard status) 17396 <1> ; BX = current character in tty/keyboard buffer 17397 <1> ; (BH = scan code, BL = ascii code) 17398 <1> ; (BX=0 if there is not a waiting character) 17399 <1> ; CX is undefined 17400 <1> ; 17401 <1> ; (if calling is for video page status) 17402 <1> ; BX = cursor position on the video page 17403 <1> ; if tty number < 8 17404 <1> ; (BH = row, BL = column) 17405 <1> ; CX = current character (in cursor position) 17406 <1> ; on the video page of the tty 17407 <1> ; if tty number < 8 17408 <1> ; (CH = color, CL = character) 17409 <1> ; 17410 <1> ; cf = 1 means error (requested tty is not ready) 17411 <1> ; 17412 <1> ; AH = FFh if the caller is not owner of 17413 <1> ; specified tty or console tty 17414 <1> ; AL = tty number (0FFh if it does not exist) 17415 <1> ; BX, CX are undefined if cf = 1 17416 <1> ; 17417 <1> ; (If tty number is 8 or 9) 17418 <1> ; AL = tty number 17419 <1> ; AH = the process number of the caller 17420 <1> ; BX = serial port status 17421 <1> ; (BH = modem status, BL = Line status) 17422 <1> ; CX = 0 17423 <1> ; 17424 <1> 17425 <1> gtty: ; get (requested) tty number 17426 <1> ; 22/02/2022 17427 <1> ; 21/02/2022 (Retro UNIX 386 v1.2, inode number modifications) 17428 <1> ; 17/10/2015 17429 <1> ; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications) 17430 <1> ; 30/05/2013 - 12/07/2014 17431 <1> ; Retro UNIX 8086 v1 modification ! 17432 <1> ; 17433 <1> ; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP)) 17434 <1> ; 17435 <1> ; 28/06/2015 (32 bit modifications) 17436 <1> ; 16/01/2014 17437 00003909 31C0 <1> xor eax, eax 17438 0000390B 6648 <1> dec ax ; 17/10/2015 17439 0000390D A3[A46C0000] <1> mov [u.r0], eax ; 0FFFFh 17440 00003912 80F901 <1> cmp cl, 1 17441 00003915 760F <1> jna short sysgtty_0 17442 <1> sysgtty_invp: 17443 <1> ; 28/06/2015 17444 00003917 C705[186D0000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 17445 0000391F 0000 <1> 17446 00003921 E93FF8FFFF <1> jmp error 17447 <1> sysgtty_0: 17448 00003926 21DB <1> and ebx, ebx 17449 00003928 7427 <1> jz short sysgtty_1 17450 <1> ; 17451 0000392A 891D[C06C0000] <1> mov [u.namep], ebx 17452 <1> ;push cx ; 23/11/2015 17453 00003930 51 <1> push ecx ; 24/12/2021 17454 00003931 E846070000 <1> call namei 17455 00003936 59 <1> pop ecx 17456 <1> ;pop cx ; 23/11/2015 17457 00003937 7213 <1> jc short sysgtty_inv_dn ; 28/06/2015 17458 <1> ; 17459 <1> ; 21/02/2022 17460 <1> ;cmp ax, 1 17461 <1> ;jna short sysgtty_2 17462 <1> ;sub ax, 10 17463 <1> ;cmp ax, 9 17464 <1> ;;ja short sysgtty_inv_dn 17465 <1> ;;mov ch, al 17466 <1> ;;jmp short sysgtty_4 17467 <1> ;; 23/11/2015 17468 <1> ;jna short sysgtty_4 17469 <1> ; 17470 <1> ; 21/02/2022 17471 <1> ; (Retro UNIX 386 v2 file system inode numbers) 17472 00003939 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 17473 0000393C 770E <1> ja short sysgtty_inv_dn 17474 <1> ;cmp al, 8 ; /dev/tty inode number is 8 17475 <1> ;jb short sysgtty_inv_dn 17476 0000393E 2C08 <1> sub al, 8 17477 00003940 720A <1> jb short sysgtty_inv_dn 17478 00003942 7416 <1> jz short sysgtty_2 ; /dev/tty inode number is 8 17479 <1> ; convert inode number to tty number (tty0 to tty9) 17480 00003944 2C09 <1> sub al, 9 17481 00003946 7204 <1> jb short sysgtty_inv_dn 17482 <1> ; al = 0 to 9 17483 00003948 29DB <1> sub ebx, ebx ; 22/02/2022 17484 0000394A EB1F <1> jmp short sysgtty_4 17485 <1> 17486 <1> sysgtty_inv_dn: 17487 <1> ;; 28/06/2015 17488 <1> ;; Invalid device name (not a tty) ! error 17489 <1> ;; (Device is not a tty or device name not found) 17490 <1> ;mov dword [u.error], ERR_INV_DEV_NAME 17491 <1> ;jmp error 17492 <1> ; 21/02/2022 17493 0000394C E935FFFFFF <1> jmp sysstty_inv_dn 17494 <1> 17495 <1> sysgtty_1: 17496 <1> ; 16/01/2014 17497 00003951 80FD0A <1> cmp ch, 10 17498 00003954 77C1 <1> ja short sysgtty_invp ; 28/06/2015 17499 00003956 FECD <1> dec ch ; 0 -> FFh (negative) 17500 00003958 790F <1> jns short sysgtty_3 ; not negative 17501 <1> sysgtty_2: 17502 <1> ; get tty number of console tty 17503 0000395A 8A25[F56C0000] <1> mov ah, [u.uno] 17504 <1> ; 28/06/2015 17505 00003960 0FB6DC <1> movzx ebx, ah 17506 00003963 8AAB[A3680000] <1> mov ch, [ebx+p.ttyc-1] 17507 <1> sysgtty_3: 17508 00003969 88E8 <1> mov al, ch 17509 <1> sysgtty_4: 17510 0000396B A2[A46C0000] <1> mov [u.r0], al 17511 <1> ; 28/06/2015 17512 <1> ;cmp al, 9 17513 <1> ;ja short sysgtty_invp 17514 00003970 8B2D[A06C0000] <1> mov ebp, [u.usp] 17515 <1> ; 23/11/2015 17516 00003976 20C9 <1> and cl, cl 17517 00003978 7432 <1> jz short sysgtty_6 ; keyboard status 17518 0000397A 3C08 <1> cmp al, 8 ; cmp ch, 8 17519 0000397C 722E <1> jb short sysgtty_6 ; video page status 17520 <1> ; serial port status 17521 <1> ; 12/07/2014 17522 <1> ;mov dx, 0 17523 <1> ;je short sysgtty_5 17524 <1> ;inc dl 17525 <1> ;sysgtty_5: 17526 <1> ; 28/06/2015 17527 0000397E 2C08 <1> sub al, 8 17528 00003980 E81AF2FFFF <1> call sp_status ; serial (COM) port (line) status 17529 <1> ; AL = Line status, AH = Modem status 17530 00003985 66894510 <1> mov [ebp+16], ax ; serial port status (in EBX) 17531 00003989 8A25[F56C0000] <1> mov ah, [u.uno] 17532 0000398F 8825[A56C0000] <1> mov [u.r0+1], ah 17533 <1> ; 24/12/2021 17534 00003995 66C745180000 <1> mov word [ebp+24], 0 ; data status (0 = not ready) 17535 <1> ; (in ECX) 17536 0000399B A880 <1> test al, 80h 17537 0000399D 7561 <1> jnz short sysgtty_dnr_err ; 29/06/2015 17538 0000399F A801 <1> test al, 1 17539 <1> ;jz sysret 17540 000039A1 7404 <1> jz short sysgtty_10 17541 000039A3 66FF4D18 <1> dec word [ebp+24] ; data status (FFFFh = ready) 17542 <1> sysgtty_10: 17543 000039A7 E9D9F7FFFF <1> jmp sysret 17544 <1> sysgtty_6: 17545 000039AC A2[D96C0000] <1> mov [u.ttyn], al ; tty number 17546 <1> ;movzx ebx, al 17547 000039B1 88C3 <1> mov bl, al ; tty number (0 to 9) 17548 000039B3 D0E3 <1> shl bl, 1 ; aligned to word 17549 <1> ; 22/04/2014 - 29/06/2015 17550 000039B5 81C3[B4670000] <1> add ebx, ttyl 17551 000039BB 8A23 <1> mov ah, [ebx] 17552 000039BD 3A25[F56C0000] <1> cmp ah, [u.uno] 17553 000039C3 7404 <1> je short sysgtty_7 17554 000039C5 20E4 <1> and ah, ah 17555 <1> ;jz short sysgtty_7 17556 000039C7 7506 <1> jnz short sysgtty_8 17557 <1> ;mov ah, 0FFh 17558 <1> sysgtty_7: 17559 000039C9 8825[A56C0000] <1> mov [u.r0+1], ah 17560 <1> sysgtty_8: 17561 000039CF 08C9 <1> or cl, cl 17562 000039D1 7510 <1> jnz short sysgtty_9 17563 000039D3 B001 <1> mov al, 1 ; test a key is available 17564 000039D5 E88F210000 <1> call getc 17565 000039DA 66894510 <1> mov [ebp+16], ax ; bx, character 17566 000039DE E9A2F7FFFF <1> jmp sysret 17567 <1> sysgtty_9: 17568 000039E3 8A1D[D96C0000] <1> mov bl, [u.ttyn] 17569 <1> ; bl = video page number 17570 000039E9 E8EC220000 <1> call get_cpos 17571 <1> ; dx = cursor position 17572 000039EE 66895510 <1> mov [ebp+16], dx ; bx 17573 <1> ;mov bl, [u.ttyn] 17574 <1> ; bl = video page number 17575 000039F2 E8F4220000 <1> call read_ac_current 17576 <1> ; ax = character and attribute/color 17577 000039F7 66894518 <1> mov [ebp+24], ax ; cx 17578 000039FB E985F7FFFF <1> jmp sysret 17579 <1> sysgtty_dnr_err: 17580 <1> ; 'device not responding !' error 17581 <1> ;mov dword [u.error], ERR_TIME_OUT ; 25 17582 00003A00 C705[186D0000]1900- <1> mov dword [u.error], ERR_DEV_NOT_RESP ; 25 17583 00003A08 0000 <1> 17584 00003A0A E956F7FFFF <1> jmp error 17585 <1> 17586 <1> ; Original UNIX v1 'sysgtty' routine: 17587 <1> ; sysgtty: 17588 <1> ;jsr r0,gtty / r1 will have offset to tty block, 17589 <1> ; / r2 has destination 17590 <1> ;mov rcsr(r1),(r2)+ / put reader control status 17591 <1> ; / in 1st word of dest 17592 <1> ;mov tcsr(r1),(r2)+ / put printer control status 17593 <1> ; / in 2nd word of dest 17594 <1> ;mov tty+4(r1),(r2)+ / put mode in 3rd word 17595 <1> ;jmp sysret2 / return to user 17596 <1> 17597 <1> ; Original UNIX v1 'gtty' routine: 17598 <1> ; gtty: 17599 <1> ;jsr r0,arg; u.off / put first arg in u.off 17600 <1> ;mov *u.r0,r1 / put file descriptor in r1 17601 <1> ;jsr r0,getf / get the i-number of the file 17602 <1> ;tst r1 / is it open for reading 17603 <1> ;bgt 1f / yes 17604 <1> ;neg r1 / no, i-number is negative, 17605 <1> ; / so make it positive 17606 <1> ;1: 17607 <1> ;sub $14.,r1 / get i-number of tty0 17608 <1> ;cmp r1,$ntty-1 / is there such a typewriter 17609 <1> ;bhis error9 / no, error 17610 <1> ;asl r1 / 0%2 17611 <1> ;asl r1 / 0%4 / yes 17612 <1> ;asl r1 / 0%8 / multiply by 8 so r1 points to 17613 <1> ; ; / tty block 17614 <1> ;mov u.off,r2 / put argument in r2 17615 <1> ;rts r0 / return 17616 %include 'u2.s' ; 11/05/2015 17617 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 17618 <1> ; (re-write kernel for test by using previous version without a major defect) 17619 <1> ; **************************************************************************** 17620 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.3) - SYS2.INC 17621 <1> ; Last Modification: 18/07/2022 17622 <1> ; ---------------------------------------------------------------------------- 17623 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 17624 <1> ; (v0.1 - Beginning: 11/07/2012) 17625 <1> ; 17626 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 17627 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 17628 <1> ; 17629 <1> ; 17630 <1> ; 17631 <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s 17632 <1> ; 17633 <1> ; **************************************************************************** 17634 <1> 17635 <1> syslink: 17636 <1> ; 12/01/2022 17637 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 17638 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 17639 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 17640 <1> ; 17641 <1> ; 'syslink' is given two arguments, name 1 and name 2. 17642 <1> ; name 1 is a file that already exists. name 2 is the name 17643 <1> ; given to the entry that will go in the current directory. 17644 <1> ; name2 will then be a link to the name 1 file. The i-number 17645 <1> ; in the name 2 entry of current directory is the same 17646 <1> ; i-number for the name 1 file. 17647 <1> ; 17648 <1> ; Calling sequence: 17649 <1> ; syslink; name 1; name 2 17650 <1> ; Arguments: 17651 <1> ; name 1 - file name to which link will be created. 17652 <1> ; name 2 - name of entry in current directory that 17653 <1> ; links to name 1. 17654 <1> ; Inputs: - 17655 <1> ; Outputs: - 17656 <1> ; ............................................................... 17657 <1> ; 17658 <1> ; Retro UNIX 8086 v1 modification: 17659 <1> ; 'syslink' system call has two arguments; so, 17660 <1> ; * 1st argument, name 1 is pointed to by BX register 17661 <1> ; * 2nd argument, name 2 is pointed to by CX register 17662 <1> ; 17663 <1> ; / name1, name2 17664 <1> ;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd 17665 00003A0F 891D[C06C0000] <1> mov [u.namep], ebx 17666 00003A15 51 <1> push ecx 17667 00003A16 E861060000 <1> call namei 17668 <1> ; jsr r0,namei / find the i-number associated with 17669 <1> ; / the 1st path name 17670 <1> ;;and ax, ax 17671 <1> ;;jz error ; File not found 17672 <1> ;jc error 17673 <1> ; br error9 / cannot be found 17674 00003A1B 730F <1> jnc short syslink0 17675 <1> ;pop ecx 17676 <1> ; 'file not found !' error 17677 00003A1D C705[186D0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 17678 00003A25 0000 <1> 17679 00003A27 E939F7FFFF <1> jmp error 17680 <1> syslink0: 17681 00003A2C E844110000 <1> call iget 17682 <1> ; jsr r0,iget / get the i-node into core 17683 00003A31 8F05[C06C0000] <1> pop dword [u.namep] ; ecx 17684 <1> ; mov (sp)+,u.namep / u.namep points to 2nd name 17685 <1> ; 24/12/2021 17686 00003A37 50 <1> push eax ; * 17687 <1> ;push ax 17688 <1> ; mov r1,-(sp) / put i-number of name1 on the stack 17689 <1> ; / (a link to this file is to be created) 17690 <1> ; 24/12/2021 17691 00003A38 8A0D[816C0000] <1> mov cl, [cdev] 17692 00003A3E 51 <1> push ecx ; ** 17693 <1> ;push word [cdev] 17694 <1> ; mov cdev,-(sp) / put i-nodes device on the stack 17695 00003A3F E8AC000000 <1> call isdir 17696 <1> ; jsr r0,isdir / is it a directory 17697 00003A44 E833060000 <1> call namei 17698 <1> ; jsr r0,namei / no, get i-number of name2 17699 <1> ;jnc error 17700 <1> ; br .+4 / not found 17701 <1> ; / so r1 = i-number of current directory 17702 <1> ; / ii = i-number of current directory 17703 <1> ; br error9 / file already exists., error 17704 00003A49 720F <1> jc short syslink1 17705 <1> ; pop eax ; 24/12/2021 17706 <1> ; pop eax 17707 <1> ; 'file exists !' error 17708 00003A4B C705[186D0000]0E00- <1> mov dword [u.error], ERR_FILE_EXISTS ; 14 17709 00003A53 0000 <1> 17710 00003A55 E90BF7FFFF <1> jmp error 17711 <1> syslink1: 17712 <1> ;pop cx 17713 <1> ; 24/12/2021 17714 00003A5A 59 <1> pop ecx ; ** 17715 <1> ;cmp cx, [cdev] 17716 00003A5B 3A0D[816C0000] <1> cmp cl, [cdev] 17717 <1> ;jne error 17718 <1> ; cmp (sp)+,cdev / u.dirp now points to 17719 <1> ; / end of current directory 17720 <1> ; bne error9 17721 00003A61 740F <1> je short syslink2 17722 <1> ; 'not same drive !' error 17723 00003A63 C705[186D0000]1500- <1> mov dword [u.error], ERR_DRV_NOT_SAME ; 21 17724 00003A6B 0000 <1> 17725 00003A6D E9F3F6FFFF <1> jmp error 17726 <1> syslink2: 17727 <1> ;pop eax ; 24/12/2021 17728 <1> ;push eax 17729 <1> ; 24/12/2021 17730 00003A72 8B0424 <1> mov eax, [esp] ; * 17731 00003A75 66A3[DC6C0000] <1> mov [u.dirbuf], ax 17732 <1> ; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf 17733 00003A7B E8C5000000 <1> call mkdir 17734 <1> ; jsr r0,mkdir / make directory entry for name2 17735 <1> ; / in current directory 17736 <1> ; 24/12/2021 17737 00003A80 58 <1> pop eax ; * 17738 <1> ;pop ax 17739 <1> ; mov (sp)+,r1 / r1 has i-number of name1 17740 00003A81 E8EF100000 <1> call iget 17741 <1> ; jsr r0,iget / get i-node into core 17742 00003A86 FE05[26680000] <1> inc byte [i.nlks] 17743 <1> ; incb i.nlks / add 1 to its number of links 17744 <1> sysunlink_2: 17745 <1> ; 12/01/2022 - Retro UNIX 386 v1.2 17746 00003A8C C605[956C0000]01 <1> mov byte [imodx], 1 ; (flag means file data is same 17747 <1> ; but inode's itself has been modified) 17748 00003A93 E86E120000 <1> call setimod 17749 <1> ; jsr r0,setimod / set the i-node modified flag 17750 00003A98 E9E8F6FFFF <1> jmp sysret 17751 <1> 17752 <1> sysunlink: 17753 <1> ; 12/01/2022 17754 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 17755 <1> ; 04/12/2015 (14 byte file names) 17756 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 17757 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 17758 <1> ; 17759 <1> ; 'sysunlink' removes the entry for the file pointed to by 17760 <1> ; name from its directory. If this entry was the last link 17761 <1> ; to the file, the contents of the file are freed and the 17762 <1> ; file is destroyed. If, however, the file was open in any 17763 <1> ; process, the actual destruction is delayed until it is 17764 <1> ; closed, even though the directory entry has disappeared. 17765 <1> ; 17766 <1> ; The error bit (e-bit) is set to indicate that the file 17767 <1> ; does not exist or that its directory can not be written. 17768 <1> ; Write permission is not required on the file itself. 17769 <1> ; It is also illegal to unlink a directory (except for 17770 <1> ; the superuser). 17771 <1> ; 17772 <1> ; Calling sequence: 17773 <1> ; sysunlink; name 17774 <1> ; Arguments: 17775 <1> ; name - name of directory entry to be removed 17776 <1> ; Inputs: - 17777 <1> ; Outputs: - 17778 <1> ; ............................................................... 17779 <1> ; 17780 <1> ; Retro UNIX 8086 v1 modification: 17781 <1> ; The user/application program puts address of the name 17782 <1> ; in BX register as 'sysunlink' system call argument. 17783 <1> 17784 <1> ; / name - remove link name 17785 00003A9D 891D[C06C0000] <1> mov [u.namep], ebx 17786 <1> ;jsr r0,arg; u.namep / u.namep points to name 17787 00003AA3 E8D4050000 <1> call namei 17788 <1> ; jsr r0,namei / find the i-number associated 17789 <1> ; / with the path name 17790 <1> ;jc error 17791 <1> ; br error9 / not found 17792 00003AA8 730F <1> jnc short sysunlink1 17793 <1> ; 'file not found !' error 17794 00003AAA C705[186D0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 17795 00003AB2 0000 <1> 17796 00003AB4 E9ACF6FFFF <1> jmp error 17797 <1> sysunlink1: 17798 00003AB9 50 <1> push eax ; 24/12/2021 17799 <1> ;push ax 17800 <1> ; mov r1,-(sp) / put its i-number on the stack 17801 00003ABA E831000000 <1> call isdir 17802 <1> ; jsr r0,isdir / is it a directory 17803 <1> ;xor ax, ax 17804 <1> ; 24/12/2021 17805 00003ABF 31C0 <1> xor eax, eax 17806 00003AC1 66A3[DC6C0000] <1> mov [u.dirbuf], ax ; 0 17807 <1> ; clr u.dirbuf / no, clear the location that will 17808 <1> ; / get written into the i-number portion 17809 <1> ; / of the entry 17810 00003AC7 832D[C46C0000]10 <1> sub dword [u.off], 16 ; 04/12/2015 (10 -> 16) 17811 <1> ; sub $10.,u.off / move u.off back 1 directory entry 17812 00003ACE E8BD000000 <1> call wdir 17813 <1> ; jsr r0,wdir / free the directory entry 17814 00003AD3 58 <1> pop eax ; 24/12/2021 17815 <1> ;pop ax 17816 <1> ; mov (sp)+,r1 / get i-number back 17817 00003AD4 E89C100000 <1> call iget 17818 <1> ; jsr r0,iget / get i-node 17819 <1> ; 12/01/2022 - Retro UNIX 386 v1.2 17820 <1> ;call setimod 17821 <1> ; ; jsr r0,setimod / set modified flag 17822 <1> ; 17823 00003AD9 FE0D[26680000] <1> dec byte [i.nlks] 17824 <1> ; decb i.nlks / decrement the number of links 17825 <1> ; 24/12/2021 17826 00003ADF 75AB <1> jnz short sysunlink_2 17827 <1> ;jnz sysret 17828 <1> ; bgt sysret9 / if this was not the last link 17829 <1> ; / to file return 17830 <1> ; 12/01/2022 - Retro UNIX 386 v1.2 17831 00003AE1 E820120000 <1> call setimod 17832 <1> ; jsr r0,setimod / set modified flag 17833 <1> ; AX = r1 = i-number 17834 00003AE6 E89B0A0000 <1> call anyi 17835 <1> ; jsr r0,anyi / if it was, see if anyone has it open. 17836 <1> ; / Then free contents of file and destroy it. 17837 00003AEB E995F6FFFF <1> jmp sysret 17838 <1> ; br sysret9 17839 <1> ;sysunlink_2: 17840 <1> ;; 12/01/2022 - Retro UNIX 386 v1.2 17841 <1> ;mov byte [imodx], 1 ; (flag means file data is same 17842 <1> ; ; but inode's itself has been modified) 17843 <1> ;call setimod 17844 <1> ; ; jsr r0,setimod / set the i-node modified flag 17845 <1> ;jmp sysret 17846 <1> 17847 <1> isdir: 17848 <1> ; 13/03/2022 17849 <1> ; 08/01/2022 17850 <1> ; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode) 17851 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 17852 <1> ; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 17853 <1> ; 17854 <1> ; 'isdir' check to see if the i-node whose i-number is in r1 17855 <1> ; is a directory. If it is, an error occurs, because 'isdir' 17856 <1> ; called by syslink and sysunlink to make sure directories 17857 <1> ; are not linked. If the user is the super user (u.uid=0), 17858 <1> ; 'isdir' does not bother checking. The current i-node 17859 <1> ; is not disturbed. 17860 <1> ; 17861 <1> ; INPUTS -> 17862 <1> ; r1 - contains the i-number whose i-node is being checked. 17863 <1> ; u.uid - user id 17864 <1> ; OUTPUTS -> 17865 <1> ; r1 - contains current i-number upon exit 17866 <1> ; (current i-node back in core) 17867 <1> ; 17868 <1> ; ((AX = R1)) 17869 <1> ; 17870 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 17871 <1> ; 17872 <1> 17873 <1> ; / if the i-node whose i-number is in r1 is a directory 17874 <1> ; / there is an error unless super user made the call 17875 <1> 17876 <1> ; 01/01/2022 17877 00003AF0 66833D[F66C0000]00 <1> cmp word [u.uid], 0 ; 16 bit uid (runix v2 fs inode) 17878 <1> ;cmp byte [u.uid], 0 17879 <1> ; tstb u.uid / super user 17880 00003AF8 764A <1> jna short isdir1 17881 <1> ; beq 1f / yes, don't care 17882 <1> ; 08/01/2022 17883 00003AFA FF35[7C6C0000] <1> push dword [ii] 17884 <1> ;push word [ii] 17885 <1> ; mov ii,-(sp) / put current i-number on stack 17886 00003B00 E870100000 <1> call iget 17887 <1> ; jsr r0,iget / get i-node into core (i-number in r1) 17888 <1> ; 01/01/2022 (runix v2 fs inode flags) 17889 00003B05 F605[25680000]80 <1> test byte [i.flgs+1], 80h ; regular file ? 17890 00003B0C 7421 <1> jz short isdir2 ; no, error! 17891 00003B0E F605[25680000]40 <1> test byte [i.flgs+1], 40h ; directory flag 17892 <1> ;test word [i.flgs], 4000h ; Bit 14 : Directory flag 17893 <1> ; bit $40000,i.flgs / is it a directory 17894 <1> ;jnz error 17895 <1> ; bne error9 / yes, error 17896 00003B15 7427 <1> jz short isdir0 17897 <1> 17898 <1> ; 13/03/2022 17899 <1> ; NOTE: 17900 <1> ; Unix v5-v7 kernels do not allow (ordinary) users 17901 <1> ; (except root/superuser) --if [u.uid] > 0-- 17902 <1> ; to link a directory. (ref: sys2.c, 'link') 17903 <1> ; 17904 <1> ; But, Retro UNIX 386 v1.2 will allow the owner of 17905 <1> ; the directory to link it. 17906 <1> 17907 00003B17 66A1[28680000] <1> mov ax, [i.uid] ; owner ID of the parent dir 17908 00003B1D 663B05[F66C0000] <1> cmp ax, [u.uid] ; user ID of current user/process 17909 00003B24 7509 <1> jne short isdir2 17910 <1> ; 13/03/2022 17911 <1> ; additional checking (may or may not be necessary!?) 17912 00003B26 663B05[F86C0000] <1> cmp ax, [u.ruid] 17913 <1> ; real (login) user ID must be same 17914 00003B2D 740F <1> je short isdir0 17915 <1> 17916 <1> isdir2: 17917 00003B2F C705[186D0000]0B00- <1> mov dword [u.error], ERR_NOT_FILE ; 11 ; ERR_DIR_ACCESS 17918 00003B37 0000 <1> 17919 <1> ; 'permission denied !' error 17920 <1> ;pop ax 17921 00003B39 E927F6FFFF <1> jmp error 17922 <1> isdir0: 17923 <1> ; 08/01/2022 17924 00003B3E 58 <1> pop eax 17925 <1> ;pop ax 17926 <1> ; mov (sp)+,r1 / no, put current i-number in r1 (ii) 17927 00003B3F E831100000 <1> call iget 17928 <1> ; jsr r0,iget / get it back in 17929 <1> isdir1: ; 1: 17930 00003B44 C3 <1> retn 17931 <1> ; rts r0 17932 <1> 17933 <1> mkdir: 17934 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 17935 <1> ; 04/12/2015 (14 byte directory names) 17936 <1> ; 12/10/2015 17937 <1> ; 17/06/2015 (Retro UNIX 386 v1 - Beginning) 17938 <1> ; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 17939 <1> ; 17940 <1> ; 'mkdir' makes a directory entry from the name pointed to 17941 <1> ; by u.namep into the current directory. 17942 <1> ; 17943 <1> ; INPUTS -> 17944 <1> ; u.namep - points to a file name 17945 <1> ; that is about to be a directory entry. 17946 <1> ; ii - current directory's i-number. 17947 <1> ; OUTPUTS -> 17948 <1> ; u.dirbuf+2 - u.dirbuf+10 - contains file name. 17949 <1> ; u.off - points to entry to be filled 17950 <1> ; in the current directory 17951 <1> ; u.base - points to start of u.dirbuf. 17952 <1> ; r1 - contains i-number of current directory 17953 <1> ; 17954 <1> ; ((AX = R1)) output 17955 <1> ; 17956 <1> ; (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM) 17957 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 17958 <1> ; 17959 <1> 17960 <1> ; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 17961 00003B45 31C0 <1> xor eax, eax 17962 00003B47 BF[DE6C0000] <1> mov edi, u.dirbuf+2 17963 00003B4C 89FE <1> mov esi, edi 17964 00003B4E AB <1> stosd 17965 00003B4F AB <1> stosd 17966 <1> ; 04/12/2015 (14 byte directory names) 17967 00003B50 AB <1> stosd 17968 00003B51 66AB <1> stosw 17969 <1> ; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this 17970 00003B53 89F7 <1> mov edi, esi ; offset to u.dirbuf 17971 <1> ; 12/10/2015 ([u.namep] -> ebp) 17972 <1> ;mov ebp, [u.namep] 17973 00003B55 E881060000 <1> call trans_addr_nmbp ; convert virtual address to physical 17974 <1> ; esi = physical address (page start + offset) 17975 <1> ; ecx = byte count in the page (1 - 4096) 17976 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 17977 <1> ; mov u.namep,r2 / r2 points to name of directory entry 17978 <1> ; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2 17979 <1> mkdir_1: ; 1: 17980 00003B5A 45 <1> inc ebp ; 12/10/2015 17981 <1> ; 17982 <1> ; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10 17983 <1> ; 01/08/2013 17984 00003B5B AC <1> lodsb 17985 <1> ; movb (r2)+,r1 / move character in name to r1 17986 00003B5C 20C0 <1> and al, al 17987 00003B5E 7426 <1> jz short mkdir_3 17988 <1> ; beq 1f / if null, done 17989 00003B60 3C2F <1> cmp al, '/' 17990 <1> ; cmp r1,$'/ / is it a "/"? 17991 00003B62 7413 <1> je short mkdir_err 17992 <1> ;je error 17993 <1> ; beq error9 / yes, error 17994 <1> ; 12/10/2015 17995 <1> ;dec cx 17996 00003B64 49 <1> dec ecx ; 24/12/2021 17997 00003B65 7505 <1> jnz short mkdir_2 17998 <1> ; 12/10/2015 ([u.namep] -> ebp) 17999 00003B67 E875060000 <1> call trans_addr_nm ; convert virtual address to physical 18000 <1> ; esi = physical address (page start + offset) 18001 <1> ; ecx = byte count in the page 18002 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 18003 <1> mkdir_2: 18004 00003B6C 81FF[EC6C0000] <1> cmp edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 18005 <1> ; cmp r3,$u.dirbuf+10. / have we reached the last slot for 18006 <1> ; / a char? 18007 00003B72 74E6 <1> je short mkdir_1 18008 <1> ; beq 1b / yes, go back 18009 00003B74 AA <1> stosb 18010 <1> ; movb r1,(r3)+ / no, put the char in the u.dirbuf 18011 00003B75 EBE3 <1> jmp short mkdir_1 18012 <1> ; br 1b / get next char 18013 <1> mkdir_err: 18014 <1> ; 17/06/2015 18015 00003B77 C705[186D0000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 18016 00003B7F 0000 <1> 18017 00003B81 E9DFF5FFFF <1> jmp error 18018 <1> 18019 <1> mkdir_3: ; 1: 18020 00003B86 A1[BC6C0000] <1> mov eax, [u.dirp] 18021 00003B8B A3[C46C0000] <1> mov [u.off], eax 18022 <1> ; mov u.dirp,u.off / pointer to empty current directory 18023 <1> ; / slot to u.off 18024 <1> ; 08/01/2022 18025 <1> wdir: ; 24/12/2021 (Retro UNIX 386 v1.2) 18026 <1> ; 29/04/2013 18027 00003B90 C705[C86C0000]- <1> mov dword [u.base], u.dirbuf 18028 00003B96 [DC6C0000] <1> 18029 <1> ; mov $u.dirbuf,u.base / u.base points to created file name 18030 00003B9A C705[CC6C0000]1000- <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 18031 00003BA2 0000 <1> 18032 <1> ; mov $10.,u.count / u.count = 10 18033 <1> ; 08/01/2022 18034 00003BA4 A1[7C6C0000] <1> mov eax, [ii] 18035 <1> ;mov ax, [ii] 18036 <1> ; mov ii,r1 / r1 has i-number of current directory 18037 <1> ;mov dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification ! 18038 <1> ; 08/01/2022 (Retro UNIX 386 v2 file system inode) 18039 00003BA9 66BA8000 <1> mov dx, 80h ; mov dx, IWRITE 18040 00003BAD E8AD100000 <1> call access 18041 <1> ; jsr r0,access; 1 / get i-node and set its file up 18042 <1> ; / for writing 18043 <1> ; AX = i-number of current directory 18044 <1> ; 01/08/2013 18045 00003BB2 FE05[166D0000] <1> inc byte [u.kcall] ; the caller is 'mkdir' sign 18046 <1> ;call writei 18047 <1> ; ; jsr r0,writei / write into directory 18048 <1> ;retn 18049 <1> ; ; rts r0 18050 <1> ; 24/12/2021 18051 00003BB8 E938150000 <1> jmp writei 18052 <1> 18053 <1> 18054 <1> ; 09/05/2022 18055 <1> ; (Retro UNIX 386 v1.2, Kernel v0.2.2.1) 18056 <1> ; 06/02/2022 18057 <1> ; 12/01/2022 18058 <1> ; 01/01/2022 18059 <1> ; 24/12/2021 18060 <1> ; 11/12/2021 18061 <1> ; 04/12/2021 18062 <1> ; 30/11/2021 18063 <1> ; 28/11/2021 - Retro UNIX 386 v1.2 18064 <1> ; (Retro UNIX 386 v2 fs compatibility modification) 18065 <1> sysexec: 18066 <1> ; 02/05/2021 18067 <1> ; 27/03/2021 18068 <1> ; 26/03/2021 18069 <1> ; 25/03/2021 (Retro UNIX 386 v2 - Beginning) 18070 <1> ; 23/10/2015 18071 <1> ; 10/10/2015, 18/10/2015, 19/10/2015 18072 <1> ; 29/07/2015, 05/08/2015, 05/08/2015 18073 <1> ; 21/07/2015, 24/07/2015, 25/07/2015 18074 <1> ; 01/07/2015, 02/07/2015, 20/07,2015 18075 <1> ; 24/06/2015, 25/06/2021 18076 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18077 <1> ; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1) 18078 <1> ; 18079 <1> ; 'sysexec' initiates execution of a file whose path name if 18080 <1> ; pointed to by 'name' in the sysexec call. 18081 <1> ; 'sysexec' performs the following operations: 18082 <1> ; 1. obtains i-number of file to be executed via 'namei'. 18083 <1> ; 2. obtains i-node of file to be executed via 'iget'. 18084 <1> ; 3. sets trap vectors to system routines. 18085 <1> ; 4. loads arguments to be passed to executing file into 18086 <1> ; highest locations of user's core 18087 <1> ; 5. puts pointers to arguments in locations immediately 18088 <1> ; following arguments. 18089 <1> ; 6. saves number of arguments in next location. 18090 <1> ; 7. initializes user's stack area so that all registers 18091 <1> ; will be zeroed and the PS is cleared and the PC set 18092 <1> ; to core when 'sysret' restores registers 18093 <1> ; and does an rti. 18094 <1> ; 8. inializes u.r0 and u.sp 18095 <1> ; 9. zeros user's core down to u.r0 18096 <1> ; 10. reads executable file from storage device into core 18097 <1> ; starting at location 'core'. 18098 <1> ; 11. sets u.break to point to end of user's code with 18099 <1> ; data area appended. 18100 <1> ; 12. calls 'sysret' which returns control at location 18101 <1> ; 'core' via 'rti' instruction. 18102 <1> ; 18103 <1> ; Calling sequence: 18104 <1> ; sysexec; namep; argp 18105 <1> ; Arguments: 18106 <1> ; namep - points to pathname of file to be executed 18107 <1> ; argp - address of table of argument pointers 18108 <1> ; argp1... argpn - table of argument pointers 18109 <1> ; argp1:<...0> ... argpn:<...0> - argument strings 18110 <1> ; Inputs: (arguments) 18111 <1> ; Outputs: - 18112 <1> ; ............................................................... 18113 <1> ; 18114 <1> ; Retro UNIX 386 v1 modification: 18115 <1> ; User application runs in it's own virtual space 18116 <1> ; which is izolated from kernel memory (and other 18117 <1> ; memory pages) via 80386 paging in ring 3 18118 <1> ; privilige mode. Virtual start address is always 0. 18119 <1> ; User's core memory starts at linear address 400000h 18120 <1> ; (the end of the 1st 4MB). 18121 <1> ; 18122 <1> ; Retro UNIX 8086 v1 modification: 18123 <1> ; user/application segment and system/kernel segment 18124 <1> ; are different and sysenter/sysret/sysrele routines 18125 <1> ; are different (user's registers are saved to 18126 <1> ; and then restored from system's stack.) 18127 <1> ; 18128 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 18129 <1> ; arguments which were in these registers; 18130 <1> ; but, it returns by putting the 1st argument 18131 <1> ; in 'u.namep' and the 2nd argument 18132 <1> ; on top of stack. (1st argument is offset of the 18133 <1> ; file/path name in the user's program segment.) 18134 <1> 18135 <1> ;call arg2 18136 <1> ; * name - 'u.namep' points to address of file/path name 18137 <1> ; in the user's program segment ('u.segmnt') 18138 <1> ; with offset in BX register (as sysopen argument 1). 18139 <1> ; * argp - sysexec argument 2 is in CX register 18140 <1> ; which is on top of stack. 18141 <1> ; 18142 <1> ; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack 18143 <1> 18144 <1> ; 23/06/2015 (32 bit modifications) 18145 <1> 18146 00003BBD 891D[C06C0000] <1> mov [u.namep], ebx ; argument 1 18147 <1> ; 18/10/2015 18148 00003BC3 890D[346D0000] <1> mov [argv], ecx ; * ; argument 2 18149 00003BC9 E8AE040000 <1> call namei 18150 <1> ; jsr r0,namei / namei returns i-number of file 18151 <1> ; / named in sysexec call in r1 18152 <1> ;jc error 18153 <1> ; br error9 18154 00003BCE 730F <1> jnc short sysexec_0 18155 <1> ; 18156 <1> ; 'file not found !' error 18157 00003BD0 C705[186D0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND 18158 00003BD8 0000 <1> 18159 00003BDA E986F5FFFF <1> jmp error 18160 <1> 18161 <1> ; 26/03/2021 - Retro UNIX 386 v2 18162 <1> ; (executable file flag is checked in 'access') 18163 <1> ; (following error message is in 'access' subroutine) 18164 <1> ;sysexec_not_exf: 18165 <1> ;; 'not executable file !' error 18166 <1> ;mov dword [u.error], ERR_NOT_EXECUTABLE 18167 <1> ;jmp error 18168 <1> sysexec_0: 18169 <1> ; 26/03/2021 ('iget' will be called in 'access') 18170 <1> ;call iget 18171 <1> ; ; jsr r0,iget / get i-node for file to be executed 18172 <1> ; 18173 <1> ;test byte [i.flgs], 10h 18174 <1> ;;test word [i.flgs], 10h 18175 <1> ; ; bit $20,i.flgs / is file executable 18176 <1> ;jz short sysexec_not_exf 18177 <1> ;;jz error 18178 <1> ; ; beq error9 18179 <1> ; 26/03/2021 18180 00003BDF 66BA4000 <1> mov dx, 40h ; IEXEC - execute, owner 18181 00003BE3 E877100000 <1> call access 18182 <1> ; ! we are here because there is execute permission ! 18183 <1> ; ('iopen' is not needed for regular files, from now on) 18184 <1> 18185 <1> ; 26/03/2021 18186 <1> ;; 25/03/2021 18187 <1> ;; (ref: Retro UNIX 386 v2, 'ux.s') 18188 <1> ;mov dx, 40h ; IEXEC - execute, owner 18189 <1> ;; 18190 <1> ;call iopen 18191 <1> ; ; jsr r0,iopen / gets i-node for file with i-number 18192 <1> ; ; / given in r1 (opens file) 18193 <1> 18194 <1> ; 26/03/2021 18195 <1> ; AX = i-number of the file 18196 <1> ;test byte [i.flgs], 20h 18197 <1> ;;test word [i.flgs], 20h 18198 <1> ; ; bit $40,i.flgs / test user id on execution bit 18199 <1> ;jz short sysexec_1 18200 <1> ; ; beq 1f 18201 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 18202 <1> ; ; tstb u.uid / test user id 18203 <1> ;jna short sysexec_1 18204 <1> ; ; beq 1f / super user 18205 <1> 18206 <1> ;mov cl, [i.uid] 18207 <1> ;mov [u.uid], cl ; 02/08/2013 18208 <1> ; ; movb i.uid,u.uid / put user id of owner of file 18209 <1> ; / as process user id 18210 <1> ; 26/03/2021 - Retro UNIX 386 v2 18211 <1> ;mov al, [i.flgs+1] 18212 00003BE8 66833D[F66C0000]00 <1> cmp word [u.uid], 0 ; super user (root) ? 18213 <1> ;jna short sysexec_19 ; yes, super user 18214 <1> ;; 02/05/2021 18215 00003BF0 7625 <1> jna short sysexec_1 ; don't set UID or GID 18216 <1> 18217 <1> ; 01/01/2022 - Retro UNIX 386 v1.2 18218 00003BF2 A0[25680000] <1> mov al, [i.flgs+1] 18219 <1> 18220 <1> ; test set user id on execution bit 18221 00003BF7 A808 <1> test al, 08h ; ISUID flag (800h) 18222 <1> ;jz short sysexec_19 18223 <1> ; 02/05/2021 18224 00003BF9 741C <1> jz short sysexec_1 ; do not set group ID 18225 <1> ; (if user ID will not be set) 18226 <1> ; (02/05/2021) 18227 <1> ; set user id on exec (800h) 18228 <1> ; 26/03/2021 18229 <1> sysexec_setuid: 18230 <1> ;; 27/03/2021 18231 <1> ;cmp word [u.uid], 0 18232 <1> ;;jna short sysexec_19 ; super user 18233 <1> ;; 02/05/2021 18234 <1> ;jna short sysexec_1 ; do not set group ID 18235 <1> ; ; (if user ID will not be set) 18236 <1> ; ; (02/05/2021) 18237 00003BFB 668B0D[28680000] <1> mov cx, [i.uid] 18238 00003C02 66890D[F66C0000] <1> mov [u.uid], cx 18239 <1> sysexec_19: 18240 <1> ; test set group id on execution bit 18241 00003C09 A804 <1> test al, 04h ; ISGID flag (400h) 18242 00003C0B 740A <1> jz short sysexec_1 18243 <1> sysexec_setgid: 18244 <1> ; set group id on exec (400h) 18245 00003C0D A0[2A680000] <1> mov al, [i.gid] 18246 00003C12 A2[FA6C0000] <1> mov [u.gid], al 18247 <1> ; 18248 <1> sysexec_1: 18249 <1> ; 06/02/2022 18250 <1> ; 12/01/2022 18251 <1> ; 24/12/2021 18252 <1> ; 11/12/2021 18253 <1> ; 04/12/2021 18254 <1> ; 10/10/2015, 18/10/2015 18255 <1> ; 21/07/2015, 24/07/2015 18256 <1> ; 24/06/2015, 25/06/2015 18257 <1> ; Moving arguments to the end of [u.upage] 18258 <1> ; (by regarding page borders in user's memory space) 18259 <1> ; 18260 <1> ; 10/10/2015 18261 <1> ; 21/07/2015 18262 00003C17 89E5 <1> mov ebp, esp ; (**) 18263 <1> ; 18/10/2015 18264 00003C19 89EF <1> mov edi, ebp 18265 00003C1B B900010000 <1> mov ecx, MAX_ARG_LEN ; 256 18266 <1> ;sub edi, MAX_ARG_LEN ; 256 18267 00003C20 29CF <1> sub edi, ecx 18268 00003C22 89FC <1> mov esp, edi 18269 00003C24 31C0 <1> xor eax, eax 18270 00003C26 A3[D06C0000] <1> mov [u.nread], eax ; 0 18271 <1> ; 12/01/2022 18272 <1> ; ([argc] must be cleared because previous 'sysexec' 18273 <1> ; may leave it with any value after an error)) 18274 00003C2B A3[306D0000] <1> mov [argc], eax ; 0 18275 <1> ; 18276 00003C30 49 <1> dec ecx ; 256 - 1 18277 00003C31 890D[CC6C0000] <1> mov [u.count], ecx ; MAX_ARG_LEN - 1 ; 255 18278 <1> ;mov dword [u.count], MAX_ARG_LEN - 1 ; 255 18279 <1> ; 24/12/2021 18280 <1> sysexec_2: 18281 00003C37 8B35[346D0000] <1> mov esi, [argv] ; 18/10/2015 18282 00003C3D E85C020000 <1> call get_argp 18283 <1> ;mov ecx, 4 18284 <1> ; 06/02/2022 18285 00003C42 31C9 <1> xor ecx, ecx 18286 00003C44 B104 <1> mov cl, 4 18287 <1> sysexec_3: 18288 00003C46 21C0 <1> and eax, eax 18289 00003C48 7454 <1> jz short sysexec_6 18290 <1> ; 18/10/2015 18291 00003C4A 010D[346D0000] <1> add [argv], ecx ; 4 18292 <1> ;;inc word [argc] 18293 <1> ; 11/12/2021 18294 <1> ;inc dword [argc] 18295 <1> ; 12/01/2022 18296 00003C50 FE05[306D0000] <1> inc byte [argc] 18297 <1> ; 18298 00003C56 A3[C86C0000] <1> mov [u.base], eax 18299 <1> ; 23/10/2015 18300 00003C5B 66C705[106D0000]00- <1> mov word [u.pcount], 0 18301 00003C63 00 <1> 18302 <1> sysexec_4: 18303 00003C64 E8C4160000 <1> call cpass ; get a character from user's core memory 18304 00003C69 750B <1> jnz short sysexec_5 18305 <1> ; (max. 255 chars + null) 18306 <1> ; 18/10/2015 18307 00003C6B 28C0 <1> sub al, al 18308 00003C6D AA <1> stosb 18309 00003C6E FF05[D06C0000] <1> inc dword [u.nread] 18310 00003C74 EB28 <1> jmp short sysexec_6 18311 <1> sysexec_5: 18312 00003C76 AA <1> stosb 18313 00003C77 20C0 <1> and al, al 18314 00003C79 75E9 <1> jnz short sysexec_4 18315 00003C7B B904000000 <1> mov ecx, 4 18316 00003C80 390D[2C6D0000] <1> cmp [ncount], ecx ; 4 18317 00003C86 72AF <1> jb short sysexec_2 18318 00003C88 8B35[286D0000] <1> mov esi, [nbase] 18319 00003C8E 010D[286D0000] <1> add [nbase], ecx ; 4 18320 <1> ;sub [ncount], cx 18321 <1> ; 11/12/2021 18322 00003C94 290D[2C6D0000] <1> sub [ncount], ecx 18323 00003C9A 8B06 <1> mov eax, [esi] 18324 00003C9C EBA8 <1> jmp short sysexec_3 18325 <1> sysexec_6: 18326 <1> ; 24/12/2021 18327 <1> ; 18/10/2015 18328 <1> ; argument list transfer from user's core memory to 18329 <1> ; kernel stack frame is OK here. 18330 <1> ; [u.nread] = argument list length 18331 <1> ;mov [argv], esp ; start address of argument list 18332 <1> ; 18333 <1> ; 18/10/2015 18334 <1> ; 24/07/2015 18335 <1> ; 21/07/2015 18336 <1> ; 02/07/2015 18337 <1> ; 25/06/2015 18338 <1> ; 24/06/2015 18339 <1> ; 23/06/2015 18340 <1> ; 18341 00003C9E 8B1D[086D0000] <1> mov ebx, [u.ppgdir] ; parent's page directory 18342 00003CA4 21DB <1> and ebx, ebx ; /etc/init ? (u.ppgdir = 0) 18343 00003CA6 740A <1> jz short sysexec_7 18344 00003CA8 A1[046D0000] <1> mov eax, [u.pgdir] ; physical address of page directory 18345 00003CAD E85DE8FFFF <1> call deallocate_page_dir 18346 <1> sysexec_7: 18347 00003CB2 E88DE7FFFF <1> call make_page_dir 18348 <1> ;jc short sysexec_14 18349 <1> ;jc panic ; allocation error 18350 <1> ; ; after a deallocation would be nonsence !? 18351 <1> ; 26/03/2021 18352 00003CB7 7243 <1> jc short sysexec_panic 18353 <1> 18354 <1> ; 24/07/2015 18355 <1> ; map kernel pages (1st 4MB) to PDE 0 18356 <1> ; of the user's page directory 18357 <1> ; (It is needed for interrupts!) 18358 <1> ; 18/10/2015 18359 00003CB9 8B15[68670000] <1> mov edx, [k_page_dir] ; Kernel's page directory 18360 00003CBF 8B02 <1> mov eax, [edx] ; physical address of 18361 <1> ; kernel's first page table (1st 4 MB) 18362 <1> ; (PDE 0 of kernel's page directory) 18363 00003CC1 8B15[046D0000] <1> mov edx, [u.pgdir] 18364 00003CC7 8902 <1> mov [edx], eax ; PDE 0 (1st 4MB) 18365 <1> ; 18366 <1> ; 20/07/2015 18367 00003CC9 BB00004000 <1> mov ebx, CORE ; start address = 0 (virtual) + CORE 18368 <1> ; 18/10/2015 18369 00003CCE BE[206D0000] <1> mov esi, pcore ; physical start address 18370 <1> sysexec_8: 18371 00003CD3 B907000000 <1> mov ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT 18372 00003CD8 E885E7FFFF <1> call make_page_table 18373 <1> ;jc panic 18374 <1> ; 26/03/2021 18375 00003CDD 721D <1> jc short sysexec_panic 18376 <1> ; 18377 <1> ;mov ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT 18378 00003CDF E88CE7FFFF <1> call make_page ; make new page, clear and set the pte 18379 <1> ;jc panic 18380 <1> ; 26/03/2021 18381 00003CE4 7216 <1> jc short sysexec_panic 18382 <1> ; 18383 00003CE6 8906 <1> mov [esi], eax ; 24/06/2015 18384 <1> ; ebx = virtual address (24/07/2015) 18385 <1> ; 30/11/2021 18386 <1> ;call add_to_swap_queue 18387 <1> ; 18/10/2015 18388 00003CE8 81FE[246D0000] <1> cmp esi, ecore ; user's stack (last) page ? 18389 00003CEE 7411 <1> je short sysexec_9 ; yes 18390 00003CF0 BE[246D0000] <1> mov esi, ecore ; physical address of the last page 18391 <1> ; 20/07/2015 18392 00003CF5 BB00F0FFFF <1> mov ebx, (ECORE - PAGE_SIZE) + CORE 18393 <1> ; ebx = virtual end address + segment base address - 4K 18394 00003CFA EBD7 <1> jmp short sysexec_8 18395 <1> sysexec_panic: 18396 <1> ; 26/03/2021 18397 00003CFC E9AAECFFFF <1> jmp panic 18398 <1> 18399 <1> sysexec_9: 18400 <1> ; 12/01/2022 18401 <1> ; 11/12/2021 18402 <1> ; 18/10/2015 18403 <1> ; 26/08/2015 18404 <1> ; 25/06/2015 18405 <1> ; move arguments from kernel stack to [ecore] 18406 <1> ; (argument list/line will be copied from kernel stack 18407 <1> ; frame to the last (stack) page of user's core memory) 18408 <1> ; 18/10/2015 18409 00003D01 8B3D[246D0000] <1> mov edi, [ecore] 18410 00003D07 81C700100000 <1> add edi, PAGE_SIZE 18411 <1> ;movzx eax, word [argc] 18412 <1> ; 12/01/2022 18413 <1> ;xor eax, eax 18414 <1> ;mov al, [argc] 18415 <1> ; [argc] < 32 18416 <1> ; 11/12/2021 18417 00003D0D A1[306D0000] <1> mov eax, [argc] 18418 00003D12 09C0 <1> or eax, eax 18419 00003D14 7509 <1> jnz short sysexec_10 18420 00003D16 89FB <1> mov ebx, edi 18421 00003D18 83EB04 <1> sub ebx, 4 18422 00003D1B 8903 <1> mov [ebx], eax ; 0 18423 00003D1D EB43 <1> jmp short sysexec_13 18424 <1> sysexec_10: 18425 00003D1F 8B0D[D06C0000] <1> mov ecx, [u.nread] 18426 <1> ;mov esi, [argv] 18427 00003D25 89E6 <1> mov esi, esp ; start address of argument list 18428 00003D27 29CF <1> sub edi, ecx ; page end address - argument list length 18429 <1> 18430 <1> ;;;; 18431 <1> ; 09/05/2022 18432 <1> ; (move edi -backward- to dword boundary) 18433 <1> ; ((this will prevent 'general protection fault' error 18434 <1> ; as result of a lodsd or dword move instruction 18435 <1> ; at the end of argument list)) 18436 00003D29 83EF03 <1> sub edi, 3 18437 00003D2C 83E7FC <1> and edi, ~3 ; (*) 18438 <1> ;;; 18439 <1> 18440 00003D2F 89C2 <1> mov edx, eax 18441 <1> ; 03/02/2022 ; ([argc] < 32) 18442 00003D31 FEC2 <1> inc dl ; argument count + 1 for argc value 18443 00003D33 C0E202 <1> shl dl, 2 ; 4 * (argument count + 1) 18444 <1> ; edx <= 128 18445 00003D36 89FB <1> mov ebx, edi 18446 <1> ; 09/05/2022 (*) - edi is already dword aligned - 18447 <1> ;and bl, 0FCh ; 32 bit (dword) alignment 18448 00003D38 29D3 <1> sub ebx, edx 18449 00003D3A 89FA <1> mov edx, edi 18450 00003D3C F3A4 <1> rep movsb 18451 00003D3E 89D6 <1> mov esi, edx 18452 00003D40 89DF <1> mov edi, ebx 18453 00003D42 BA00F0BFFF <1> mov edx, ECORE - PAGE_SIZE ; virtual addr. of the last page 18454 00003D47 2B15[246D0000] <1> sub edx, [ecore] ; difference (virtual - physical) 18455 00003D4D AB <1> stosd ; eax = argument count 18456 <1> sysexec_11: 18457 00003D4E 89F0 <1> mov eax, esi 18458 00003D50 01D0 <1> add eax, edx 18459 00003D52 AB <1> stosd ; eax = virtual address 18460 00003D53 FE0D[306D0000] <1> dec byte [argc] 18461 00003D59 7407 <1> jz short sysexec_13 18462 <1> sysexec_12: 18463 00003D5B AC <1> lodsb 18464 00003D5C 20C0 <1> and al, al 18465 00003D5E 75FB <1> jnz short sysexec_12 18466 00003D60 EBEC <1> jmp short sysexec_11 18467 <1> ; 18468 <1> ; 1: 18469 <1> ; mov (sp)+,r5 / r5 now contains address of list of 18470 <1> ; / pointers to arguments to be passed 18471 <1> ; mov $1,u.quit / u.quit determines handling of quits; 18472 <1> ; / u.quit = 1 take quit 18473 <1> ; mov $1,u.intr / u.intr determines handling of 18474 <1> ; / interrupts; u.intr = 1 take interrupt 18475 <1> ; mov $rtssym,30 / emt trap vector set to take 18476 <1> ; / system routine 18477 <1> ; mov $fpsym,*10 / reserved instruction trap vector 18478 <1> ; / set to take system routine 18479 <1> ; mov $sstack,sp / stack space used during swapping 18480 <1> ; mov r5,-(sp) / save arguments pointer on stack 18481 <1> ; mov $ecore,r5 / r5 has end of core 18482 <1> ; mov $core,r4 / r4 has start of users core 18483 <1> ; mov r4,u.base / u.base has start of users core 18484 <1> ; mov (sp),r2 / move arguments list pointer into r2 18485 <1> ; 1: 18486 <1> ; tst (r2)+ / argument char = "nul" 18487 <1> ; bne 1b 18488 <1> ; tst -(r2) / decrement r2 by 2; r2 has addr of 18489 <1> ; / end of argument pointer list 18490 <1> ; 1: 18491 <1> ; / move arguments to bottom of users core 18492 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 18493 <1> ; cmp r2,(sp) / is r2 = beginning of argument 18494 <1> ; / ptr list 18495 <1> ; blo 1f / branch to 1f when all arguments 18496 <1> ; / are moved 18497 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 18498 <1> ; 2: 18499 <1> ; tstb (r3)+ 18500 <1> ; bne 2b / scan argument for \0 (nul) 18501 <1> 18502 <1> ; 2: 18503 <1> ; movb -(r3),-(r5) / move argument char 18504 <1> ; / by char starting at "ecore" 18505 <1> ; cmp r3,(r2) / moved all characters in 18506 <1> ; / this argument 18507 <1> ; bhi 2b / branch 2b if not 18508 <1> ; mov r5,(r4)+ / move r5 into top of users core; 18509 <1> ; / r5 has pointer to nth arg 18510 <1> ; br 1b / string 18511 <1> ; 1: 18512 <1> ; clrb -(r5) 18513 <1> ; bic $1,r5 / make r5 even, r5 points to 18514 <1> ; / last word of argument strings 18515 <1> ; mov $core,r2 18516 <1> 18517 <1> ; 1: / move argument pointers into core following 18518 <1> ; / argument strings 18519 <1> ; cmp r2,r4 18520 <1> ; bhis 1f / branch to 1f when all pointers 18521 <1> ; / are moved 18522 <1> ; mov (r2)+,-(r5) 18523 <1> ; br 1b 18524 <1> ; 1: 18525 <1> ; sub $core,r4 / gives number of arguments *2 18526 <1> ; asr r4 / divide r4 by 2 to calculate 18527 <1> ; / the number of args stored 18528 <1> ; mov r4,-(r5) / save number of arguments ahead 18529 <1> ; / of the argument pointers 18530 <1> sysexec_13: 18531 <1> ; 30/11/2021 18532 <1> ; 28/11/2021 18533 <1> ; 19/10/2015 18534 <1> ; 18/10/2015 18535 <1> ; 29/07/2015 18536 <1> ; 25/07/2015 18537 <1> ; 24/07/2015 18538 <1> ; 20/07/2015 18539 <1> ; 25/06/2015 18540 <1> ; 24/06/2015 18541 <1> ; 23/06/2015 18542 <1> ; 18543 <1> ; moving arguments to [ecore] is OK here.. 18544 <1> ; 18/10/2015 18545 00003D62 89EC <1> mov esp, ebp ; (**) restore kernel stack pointer 18546 <1> ; ebx = beginning address of argument list pointers 18547 <1> ; in user's stack 18548 <1> ; 19/10/2015 18549 00003D64 2B1D[246D0000] <1> sub ebx, [ecore] 18550 00003D6A 81C300F0BFFF <1> add ebx, (ECORE - PAGE_SIZE) 18551 <1> ; end of core - 4096 (last page) 18552 <1> ; (virtual address) 18553 00003D70 891D[346D0000] <1> mov [argv], ebx 18554 00003D76 891D[D46C0000] <1> mov [u.break], ebx ; available user memory 18555 <1> ; 18556 00003D7C 29C0 <1> sub eax, eax 18557 00003D7E C705[CC6C0000]2000- <1> mov dword [u.count], 32 ; Executable file header size 18558 00003D86 0000 <1> 18559 <1> ; mov $14,u.count 18560 00003D88 C705[B86C0000]- <1> mov dword [u.fofp], u.off 18561 00003D8E [C46C0000] <1> 18562 <1> ; mov $u.off,u.fofp 18563 00003D92 A3[C46C0000] <1> mov [u.off], eax ; 0 18564 <1> ; clr u.off / set offset in file to be read to zero 18565 <1> ; 25/07/2015 18566 00003D97 A3[C86C0000] <1> mov [u.base], eax ; 0, start of user's core (virtual) 18567 <1> ; 25/06/2015 18568 00003D9C A1[7C6C0000] <1> mov eax, [ii] ; 28/11/2021 (32 bit inode number) 18569 <1> ; AX = i-number of the executable file 18570 00003DA1 E83B110000 <1> call readi 18571 <1> ; jsr r0,readi / read in first six words of 18572 <1> ; / user's file, starting at $core 18573 <1> ; mov sp,r5 / put users stack address in r5 18574 <1> ; sub $core+40.,r5 / subtract $core +40, 18575 <1> ; / from r5 (leaves number of words 18576 <1> ; / less 26 available for 18577 <1> ; / program in user core 18578 <1> ; mov r5,u.count / 18579 <1> ; 25/06/2015 18580 00003DA6 8B0D[D46C0000] <1> mov ecx, [u.break] ; top of user's stack (physical addr.) 18581 00003DAC 890D[CC6C0000] <1> mov [u.count], ecx ; save for overrun check 18582 <1> ; 18583 00003DB2 8B0D[D06C0000] <1> mov ecx, [u.nread] 18584 00003DB8 890D[D46C0000] <1> mov [u.break], ecx ; virtual address (offset from start) 18585 00003DBE 80F920 <1> cmp cl, 32 18586 00003DC1 7540 <1> jne short sysexec_15 18587 <1> ;: 18588 <1> ; 25/06/2015 18589 <1> ; Retro UNIX 386 v1 (32 bit) executable file header format 18590 <1> ; 18/10/2015 18591 00003DC3 8B35[206D0000] <1> mov esi, [pcore] ; start address of user's core memory 18592 <1> ; (phys. start addr. of the exec. file) 18593 00003DC9 AD <1> lodsd 18594 00003DCA 663DEB1E <1> cmp ax, 1EEBh ; EBh, 1Eh -> jump to +32 18595 00003DCE 7533 <1> jne short sysexec_15 18596 <1> ; cmp core,$405 / br .+14 is first instruction 18597 <1> ; / if file is standard a.out format 18598 <1> ; bne 1f / branch, if not standard format 18599 00003DD0 AD <1> lodsd 18600 00003DD1 89C1 <1> mov ecx, eax ; text (code) section size 18601 00003DD3 AD <1> lodsd 18602 00003DD4 01C1 <1> add ecx, eax ; + data section size (initialized data) 18603 <1> ; mov core+2,r5 / put 2nd word of users program in r5; 18604 <1> ; / number of bytes in program text 18605 <1> ; sub $14,r5 / subtract 12 18606 00003DD6 89CB <1> mov ebx, ecx 18607 <1> ; 18608 <1> ; 25/06/2015 18609 <1> ; NOTE: These are for next versions of Retro UNIX 386 18610 <1> ; and SINGLIX operating systems (as code template). 18611 <1> ; Current Retro UNIX 386 v1 files can be max. 64KB 18612 <1> ; due to RUFS (floppy disk file system) restriction... 18613 <1> ; Overrun is not possible for current version. 18614 <1> ; 18615 00003DD8 AD <1> lodsd 18616 00003DD9 01C3 <1> add ebx, eax ; + bss section size (for overrun checking) 18617 00003DDB 3B1D[CC6C0000] <1> cmp ebx, [u.count] 18618 00003DE1 7711 <1> ja short sysexec_14 ; program overruns stack ! 18619 <1> ; 18620 <1> ; 24/07/2015 18621 <1> ; add bss section size to [u.break] 18622 00003DE3 0105[D46C0000] <1> add [u.break], eax 18623 <1> ; 18624 00003DE9 83E920 <1> sub ecx, 32 ; header size (already loaded) 18625 <1> ;cmp ecx, [u.count] 18626 <1> ;jnb short sysexec_16 18627 <1> ; cmp r5,u.count / 18628 <1> ; bgt 1f / branch if r5 greater than u.count 18629 00003DEC 890D[CC6C0000] <1> mov [u.count], ecx ; required read count 18630 <1> ; mov r5,u.count 18631 <1> ; 18632 00003DF2 EB29 <1> jmp short sysexec_16 18633 <1> ; 18634 <1> sysexec_14: 18635 <1> ; 23/06/2015 18636 <1> ; insufficient (out of) memory 18637 00003DF4 C705[186D0000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; 1 18638 00003DFC 0000 <1> 18639 00003DFE E962F3FFFF <1> jmp error 18640 <1> ; 18641 <1> sysexec_15: 18642 <1> ; 25/06/2015 18643 <1> ;movzx edx, word [i.size] ; file size 18644 <1> ; 30/11/2021 18645 00003E03 8B15[2C680000] <1> mov edx, [i.size] ; file size 18646 00003E09 29CA <1> sub edx, ecx ; file size - loaded bytes 18647 00003E0B 7626 <1> jna short sysexec_17 ; no need to next read 18648 00003E0D 01D1 <1> add ecx, edx ; [i.size] 18649 00003E0F 3B0D[CC6C0000] <1> cmp ecx, [u.count] ; overrun check (!) 18650 00003E15 77DD <1> ja short sysexec_14 18651 00003E17 8915[CC6C0000] <1> mov [u.count], edx 18652 <1> sysexec_16: 18653 <1> ;mov ax, [ii] ; i-number 18654 <1> ; 28/11/2021 18655 00003E1D A1[7C6C0000] <1> mov eax, [ii] ; 32 bit inode number 18656 00003E22 E8BA100000 <1> call readi 18657 <1> ; add core+10,u.nread / add size of user data area 18658 <1> ; / to u.nread 18659 <1> ; br 2f 18660 <1> ; 1: 18661 <1> ; jsr r0,readi / read in rest of file 18662 <1> ; 2: 18663 00003E27 8B0D[D06C0000] <1> mov ecx, [u.nread] 18664 00003E2D 010D[D46C0000] <1> add [u.break], ecx 18665 <1> ; mov u.nread,u.break / set users program break to end of 18666 <1> ; / user code 18667 <1> ; add $core+14,u.break / plus data area 18668 <1> ; 20/07/2015 18669 <1> sysexec_17: 18670 <1> ; 26/03/2021 - Retro UNIX 386 v2 18671 <1> ; ('iclose' is not needed for regular files, from now on) 18672 <1> ;;mov ax, [ii] ; i-number 18673 <1> ;call iclose 18674 <1> ; ; jsr r0,iclose / does nothing 18675 00003E33 31C0 <1> xor eax, eax 18676 00003E35 FEC0 <1> inc al 18677 00003E37 66A3[F06C0000] <1> mov [u.intr], ax ; 1 (interrupt/time-out is enabled) 18678 00003E3D 66A3[F26C0000] <1> mov [u.quit], ax ; 1 ('crtl+brk' signal is enabled) 18679 <1> ; 30/11/2021 18680 00003E43 FEC8 <1> dec al ; eax = 0 18681 <1> ; 02/07/2015 18682 <1> ;cmp dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ? 18683 00003E45 3905[086D0000] <1> cmp [u.ppgdir], eax ; 0 ; is the caller sys_init (kernel) ? 18684 00003E4B 770C <1> ja short sysexec_18 ; no, the caller is user process 18685 <1> ; If the caller is kernel (sys_init), 'sysexec' will come here 18686 00003E4D 8B15[68670000] <1> mov edx, [k_page_dir] ; kernel's page directory 18687 00003E53 8915[086D0000] <1> mov [u.ppgdir], edx ; next time 'sysexec' must not come here 18688 <1> sysexec_18: 18689 <1> ; 18/10/2015 18690 <1> ; 05/08/2015 18691 <1> ; 29/07/2015 18692 00003E59 8B2D[346D0000] <1> mov ebp, [argv] ; user's stack pointer must points to argument 18693 <1> ; list pointers (argument count) 18694 00003E5F FA <1> cli 18695 00003E60 8B25[04670000] <1> mov esp, [tss.esp0] ; ring 0 (kernel) stack pointer 18696 <1> ;mov esp, [u.sp] ; Restore Kernel stack 18697 <1> ; for this process 18698 <1> ;add esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS 18699 <1> ;;xor eax, eax ; 0 18700 <1> ;dec al ; eax = 0 18701 <1> ; eax = 0 ; 30/11/2021 18702 00003E66 66BA2300 <1> mov dx, UDATA 18703 00003E6A 6652 <1> push dx ; user's stack segment 18704 00003E6C 55 <1> push ebp ; user's stack pointer 18705 <1> ; (points to number of arguments) 18706 00003E6D FB <1> sti 18707 00003E6E 9C <1> pushfd ; EFLAGS 18708 <1> ; Set IF for enabling interrupts in user mode 18709 <1> ;or dword [esp], 200h 18710 <1> ; 18711 <1> ;mov bx, UCODE 18712 <1> ;push bx ; user's code segment 18713 00003E6F 6A1B <1> push UCODE 18714 <1> ;push 0 18715 00003E71 50 <1> push eax ; EIP (=0) - start address - 18716 <1> ; clr -(r5) / popped into ps when rti in 18717 <1> ; / sysrele is executed 18718 <1> ; mov $core,-(r5) / popped into pc when rti 18719 <1> ; / in sysrele is executed 18720 <1> ;mov r5,0f / load second copyz argument 18721 <1> ;tst -(r5) / decrement r5 18722 00003E72 8925[9C6C0000] <1> mov [u.sp], esp ; 29/07/2015 18723 <1> ; 05/08/2015 18724 <1> ; Remedy of a General Protection Fault during 'iretd' is here ! 18725 <1> ; ('push dx' would cause to general protection fault, 18726 <1> ; after 'pop ds' etc.) 18727 <1> ; 18728 <1> ;; push dx ; ds (UDATA) 18729 <1> ;; push dx ; es (UDATA) 18730 <1> ;; push dx ; fs (UDATA) 18731 <1> ;; push dx ; gs (UDATA) 18732 <1> ; 18733 <1> ; This is a trick to prevent general protection fault 18734 <1> ; during 'iretd' intruction at the end of 'sysrele' (in u1.s): 18735 00003E78 8EC2 <1> mov es, dx ; UDATA 18736 00003E7A 06 <1> push es ; ds (UDATA) 18737 00003E7B 06 <1> push es ; es (UDATA) 18738 00003E7C 06 <1> push es ; fs (UDATA) 18739 00003E7D 06 <1> push es ; gs (UDATA) 18740 00003E7E 66BA1000 <1> mov dx, KDATA 18741 00003E82 8EC2 <1> mov es, dx 18742 <1> ; 18743 <1> ;; pushad simulation 18744 00003E84 89E5 <1> mov ebp, esp ; esp before pushad 18745 00003E86 50 <1> push eax ; eax (0) 18746 00003E87 50 <1> push eax ; ecx (0) 18747 00003E88 50 <1> push eax ; edx (0) 18748 00003E89 50 <1> push eax ; ebx (0) 18749 00003E8A 55 <1> push ebp ; esp before pushad 18750 00003E8B 50 <1> push eax ; ebp (0) 18751 00003E8C 50 <1> push eax ; esi (0) 18752 00003E8D 50 <1> push eax ; edi (0) 18753 <1> ; 18754 00003E8E A3[A46C0000] <1> mov [u.r0], eax ; eax = 0 18755 00003E93 8925[A06C0000] <1> mov [u.usp], esp 18756 <1> ; mov r5,u.r0 / 18757 <1> ; sub $16.,r5 / skip 8 words 18758 <1> ; mov r5,u.sp / assign user stack pointer value, 18759 <1> ; / effectively zeroes all regs 18760 <1> ; / when sysrele is executed 18761 <1> ; jsr r0,copyz; core; 0:0 / zero user's core 18762 <1> ; clr u.break 18763 <1> ; mov r5,sp / point sp to user's stack 18764 <1> ; 18765 00003E99 E9E9F2FFFF <1> jmp sysret0 18766 <1> ;jmp sysret 18767 <1> ; br sysret3 / return to core image at $core 18768 <1> 18769 <1> get_argp: 18770 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 18771 <1> ; 18/10/2015 (nbase, ncount) 18772 <1> ; 21/07/2015 18773 <1> ; 24/06/2015 (Retro UNIX 386 v1) 18774 <1> ; Get (virtual) address of argument from user's core memory 18775 <1> ; 18776 <1> ; INPUT: 18777 <1> ; esi = virtual address of argument pointer 18778 <1> ; OUTPUT: 18779 <1> ; eax = virtual address of argument 18780 <1> ; 18781 <1> ; Modified registers: EAX, EBX, ECX, EDX, ESI 18782 <1> ; 18783 00003E9E 833D[086D0000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? 18784 <1> ; (the caller is kernel) 18785 00003EA5 767C <1> jna short get_argpk 18786 <1> ; 18787 00003EA7 89F3 <1> mov ebx, esi 18788 00003EA9 E819E9FFFF <1> call get_physical_addr ; get physical address 18789 00003EAE 7254 <1> jc short get_argp_err ; 11/12/2021 18790 00003EB0 A3[286D0000] <1> mov [nbase], eax ; physical address 18791 <1> ;mov [ncount], cx ; remain byte count in page (1-4096) 18792 <1> ; 11/12/2021 18793 00003EB5 890D[2C6D0000] <1> mov [ncount], ecx 18794 00003EBB B804000000 <1> mov eax, 4 ; 21/07/2015 18795 <1> ;cmp cx, ax ; 4 18796 <1> ; 11/12/2021 18797 00003EC0 39C1 <1> cmp ecx, eax ; 4 18798 00003EC2 734A <1> jnb short get_argp2 18799 00003EC4 89F3 <1> mov ebx, esi 18800 00003EC6 01CB <1> add ebx, ecx 18801 00003EC8 E8FAE8FFFF <1> call get_physical_addr ; get physical address 18802 00003ECD 7235 <1> jc short get_argp_err 18803 <1> ;push esi 18804 00003ECF 89C6 <1> mov esi, eax 18805 <1> ;xchg cx, [ncount] 18806 <1> ; 11/12/2021 18807 00003ED1 870D[2C6D0000] <1> xchg ecx, [ncount] 18808 00003ED7 8735[286D0000] <1> xchg esi, [nbase] 18809 00003EDD B504 <1> mov ch, 4 18810 00003EDF 28CD <1> sub ch, cl 18811 <1> get_argp0: 18812 00003EE1 AC <1> lodsb 18813 <1> ;push ax 18814 <1> ; 11/12/2021 18815 00003EE2 50 <1> push eax 18816 00003EE3 FEC9 <1> dec cl 18817 00003EE5 75FA <1> jnz short get_argp0 18818 00003EE7 8B35[286D0000] <1> mov esi, [nbase] 18819 <1> ; 21/07/2015 18820 00003EED 0FB6C5 <1> movzx eax, ch 18821 00003EF0 0105[286D0000] <1> add [nbase], eax 18822 <1> ;sub [ncount], ax 18823 <1> ; 11/12/2021 18824 00003EF6 2905[2C6D0000] <1> sub [ncount], eax 18825 <1> get_argp1: 18826 00003EFC AC <1> lodsb 18827 00003EFD FECD <1> dec ch 18828 00003EFF 743B <1> jz short get_argp3 18829 <1> ;push ax 18830 <1> ; 11/12/2021 18831 00003F01 50 <1> push eax 18832 00003F02 EBF8 <1> jmp short get_argp1 18833 <1> get_argp_err: 18834 00003F04 A3[186D0000] <1> mov [u.error], eax 18835 00003F09 E957F2FFFF <1> jmp error 18836 <1> get_argp2: 18837 <1> ; 21/07/2015 18838 <1> ;mov eax, 4 18839 00003F0E 8B15[286D0000] <1> mov edx, [nbase] ; 18/10/2015 18840 00003F14 0105[286D0000] <1> add [nbase], eax 18841 <1> ;sub [ncount], ax 18842 <1> ; 11/12/2021 18843 00003F1A 2905[2C6D0000] <1> sub [ncount], eax 18844 <1> ; 18845 00003F20 8B02 <1> mov eax, [edx] 18846 00003F22 C3 <1> retn 18847 <1> get_argpk: 18848 <1> ; Argument is in kernel's memory space 18849 00003F23 66C705[2C6D0000]00- <1> mov word [ncount], PAGE_SIZE ; 4096 18850 00003F2B 10 <1> 18851 00003F2C 8935[286D0000] <1> mov [nbase], esi 18852 00003F32 8305[286D0000]04 <1> add dword [nbase], 4 18853 00003F39 8B06 <1> mov eax, [esi] ; virtual addr. = physical addr. 18854 00003F3B C3 <1> retn 18855 <1> get_argp3: 18856 00003F3C B103 <1> mov cl, 3 18857 <1> get_argp4: 18858 00003F3E C1E008 <1> shl eax, 8 18859 <1> ;pop dx 18860 <1> ; 11/12/2021 18861 00003F41 5A <1> pop edx 18862 00003F42 88D0 <1> mov al, dl 18863 00003F44 E2F8 <1> loop get_argp4 18864 <1> ;pop esi 18865 00003F46 C3 <1> retn 18866 <1> 18867 <1> sysfstat: 18868 <1> ; 09/05/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.1) 18869 <1> ; ([idev] return in eax) 18870 <1> ; 0 = root device 18871 <1> ; 1 = mounted device (>0) 18872 <1> ; 06/02/2022 18873 <1> ; 08/01/2022 18874 <1> ; 26/12/2021 (Retro UNIX 386 v1.2) 18875 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18876 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 18877 <1> ; 18878 <1> ; 'sysfstat' is identical to 'sysstat' except that it operates 18879 <1> ; on open files instead of files given by name. It puts the 18880 <1> ; buffer address on the stack, gets the i-number and 18881 <1> ; checks to see if the file is open for reading or writing. 18882 <1> ; If the file is open for writing (i-number is negative) 18883 <1> ; the i-number is set positive and a branch into 'sysstat' 18884 <1> ; is made. 18885 <1> ; 18886 <1> ; Calling sequence: 18887 <1> ; sysfstat; buf 18888 <1> ; Arguments: 18889 <1> ; buf - buffer address 18890 <1> ; 18891 <1> ; Inputs: *u.r0 - file descriptor 18892 <1> ; Outputs: buffer is loaded with file information 18893 <1> ; ............................................................... 18894 <1> ; 18895 <1> ; Retro UNIX 8086 v1 modification: 18896 <1> ; 'sysfstat' system call has two arguments; so, 18897 <1> ; * 1st argument, file descriptor is in BX register 18898 <1> ; * 2nd argument, buf is pointed to by CX register 18899 <1> 18900 <1> ; / set status of open file 18901 <1> ; jsr r0,arg; u.off / put buffer address in u.off 18902 00003F47 51 <1> push ecx ; * 18903 <1> ; mov u.off,-(sp) / put buffer address on the stack 18904 <1> ; mov *u.r0,r1 / put file descriptor in r1 18905 <1> ; jsr r0,getf / get the files i-number 18906 <1> ; BX = file descriptor (file number) 18907 00003F48 E8F9000000 <1> call getf1 18908 <1> ; 06/02/2022 18909 00003F4D 21C0 <1> and eax, eax 18910 <1> ;and ax, ax ; i-number of the file 18911 <1> ; tst r1 / is it 0? 18912 <1> ;jz error 18913 <1> ; beq error3 / yes, error 18914 <1> ;jnz short sysfstat1 18915 <1> ; 26/12/2021 - Retro UNIX 386 v1.2 (runix v2 file system) 18916 00003F4F 752C <1> jnz short sysstat1 18917 00003F51 C705[186D0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 18918 00003F59 0000 <1> 18919 00003F5B E905F2FFFF <1> jmp error 18920 <1> ; 26/12/2021 18921 <1> ;sysfstat1: 18922 <1> ;cmp ah, 80h 18923 <1> ;jb short sysstat1 18924 <1> ; ; bgt 1f / if i-number is negative (open for writing) 18925 <1> ;neg ax 18926 <1> ; ; neg r1 / make it positive, then branch 18927 <1> ; 08/01/2022 18928 <1> ;jmp short sysstat1 18929 <1> ; br 1f / to 1f 18930 <1> sysstat: 18931 <1> ; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3) 18932 <1> ; ([idev] return in eax) 18933 <1> ; 0 = root device 18934 <1> ; 1 = mounted device (>0) 18935 <1> ; 26/12/2021 (Retro UNIX 386 v1.2) 18936 <1> ; 18/10/2015 18937 <1> ; 07/10/2015 18938 <1> ; 02/09/2015 18939 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18940 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 18941 <1> ; 18942 <1> ; 'sysstat' gets the status of a file. Its arguments are the 18943 <1> ; name of the file and buffer address. The buffer is 34 bytes 18944 <1> ; long and information about the file placed in it. 18945 <1> ; sysstat calls 'namei' to get the i-number of the file. 18946 <1> ; Then 'iget' is called to get i-node in core. The buffer 18947 <1> ; is then loaded and the results are given in the UNIX 18948 <1> ; Programmers Manual sysstat (II). 18949 <1> ; 18950 <1> ; Calling sequence: 18951 <1> ; sysstat; name; buf 18952 <1> ; Arguments: 18953 <1> ; name - points to the name of the file 18954 <1> ; buf - address of a 34 bytes buffer 18955 <1> ; Inputs: - 18956 <1> ; Outputs: buffer is loaded with file information 18957 <1> ; ............................................................... 18958 <1> ; 18959 <1> ; Retro UNIX 8086 v1 modification: 18960 <1> ; 'sysstat' system call has two arguments; so, 18961 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 18962 <1> ; to get sysstat system call arguments from the user; 18963 <1> ; * 1st argument, name is pointed to by BX register 18964 <1> ; * 2nd argument, buf is pointed to by CX register 18965 <1> ; 18966 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 18967 <1> ; arguments which were in these registers; 18968 <1> ; but, it returns by putting the 1st argument 18969 <1> ; in 'u.namep' and the 2nd argument 18970 <1> ; on top of stack. (1st argument is offset of the 18971 <1> ; file/path name in the user's program segment.) 18972 <1> 18973 <1> ; / ; name of file; buffer - get files status 18974 <1> ; jsr r0,arg2 / get the 2 arguments 18975 00003F60 891D[C06C0000] <1> mov [u.namep], ebx 18976 00003F66 51 <1> push ecx ; * 18977 00003F67 E810010000 <1> call namei 18978 <1> ; jsr r0,namei / get the i-number for the file 18979 <1> ;jc error 18980 <1> ; br error3 / no such file, error 18981 00003F6C 730F <1> jnc short sysstat1 18982 <1> ; pop ecx 18983 <1> sysstat_err0: 18984 <1> ; 'file not found !' error 18985 00003F6E C705[186D0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 18986 00003F76 0000 <1> 18987 00003F78 E9E8F1FFFF <1> jmp error 18988 <1> 18989 <1> sysstat1: ; 1: 18990 00003F7D E8F30B0000 <1> call iget 18991 <1> ; jsr r0,iget / get the i-node into core 18992 <1> ; 07/10/2015 (ax = [ii], inode number) 18993 <1> ; 02/09/2015 18994 00003F82 8F05[C86C0000] <1> pop dword [u.base] ; * 18995 <1> ; mov (sp)+,r3 / move u.off to r3 (points to buffer) 18996 00003F88 E861000000 <1> call sysstat_gpa ; get physical address 18997 00003F8D 730A <1> jnc short sysstat2 18998 <1> sysstat_err1: 18999 00003F8F A3[186D0000] <1> mov dword [u.error], eax ; error code 19000 00003F94 E9CCF1FFFF <1> jmp error 19001 <1> sysstat2: 19002 00003F99 A0[7C6C0000] <1> mov al, [ii] ; 07/10/2015 (result of 'iget' call, above) 19003 00003F9E AA <1> stosb 19004 00003F9F FF05[C86C0000] <1> inc dword [u.base] 19005 <1> ;dec cx 19006 00003FA5 49 <1> dec ecx ; 26/12/2021 19007 00003FA6 7505 <1> jnz short sysstat3 19008 00003FA8 E841000000 <1> call sysstat_gpa 19009 <1> ;jc short sysstat_err1 19010 <1> sysstat3: 19011 00003FAD A0[7D6C0000] <1> mov al, [ii+1] ; 07/10/2015 (result of 'iget' call, above) 19012 00003FB2 AA <1> stosb 19013 <1> ; mov r1,(r3)+ / put i-number in 1st word of buffer 19014 00003FB3 FF05[C86C0000] <1> inc dword [u.base] 19015 <1> ;;dec word [u.pcount] 19016 <1> ;dec cx 19017 00003FB9 49 <1> dec ecx ; 26/12/2021 19018 00003FBA 7505 <1> jnz short sysstat4 19019 00003FBC E82D000000 <1> call sysstat_gpa 19020 <1> ;jc short sysstat_err1 19021 <1> sysstat4: 19022 00003FC1 BE[24680000] <1> mov esi, inode 19023 <1> ; mov $inode,r2 / r2 points to i-node 19024 <1> sysstat5: ; 1: 19025 00003FC6 A4 <1> movsb 19026 <1> ; mov (r2)+,(r3)+ / move rest of i-node to buffer 19027 00003FC7 FF05[C86C0000] <1> inc dword [u.base] 19028 <1> ;;dec word [u.pcount] 19029 <1> ;dec cx 19030 00003FCD 49 <1> dec ecx ; 26/12/2021 19031 00003FCE 7505 <1> jnz short sysstat6 19032 00003FD0 E819000000 <1> call sysstat_gpa 19033 <1> ;jc short sysstat_err1 19034 <1> sysstat6: 19035 <1> ; 26/12/2021 - Retro UNIX 386 v1.2 19036 00003FD5 81FE[64680000] <1> cmp esi, inode + 64 ; Retro UNIX v2 inode 19037 <1> ;cmp esi, inode + 32 19038 <1> ; cmp r2,$inode+32 / done? 19039 00003FDB 75E9 <1> jne short sysstat5 19040 <1> ; bne 1b / no, go back 19041 <1> 19042 <1> ;;; 19043 <1> ; 09/05/2022 19044 <1> ;*** additional feature *** -retro unix only- 19045 <1> ; 19046 <1> ; !! return device number -of current inode- in eax !! 19047 <1> ; 19048 <1> ; (modification reason/purpose: 19049 <1> ; to improve 'pwd' command's pathname output/result 19050 <1> ; and to correct 'cp' command's 'can not copy file itself' 19051 <1> ; error due to same inode numbers in root file system 19052 <1> ; and mounted file system.) 19053 <1> ; 19054 00003FDD 29C0 <1> sub eax, eax 19055 00003FDF A0[806C0000] <1> mov al, [idev] ; [cdev] 19056 00003FE4 A3[A46C0000] <1> mov [u.r0], eax 19057 <1> ;;; 19058 <1> 19059 00003FE9 E997F1FFFF <1> jmp sysret 19060 <1> ; br sysret3 / return through sysret 19061 <1> ; 19062 <1> sysstat_gpa: ; get physical address of file status buffer 19063 <1> ; 02/09/2015 19064 00003FEE 8B1D[C86C0000] <1> mov ebx, [u.base] 19065 <1> ; 07/10/2015 19066 00003FF4 E8CEE7FFFF <1> call get_physical_addr ; get physical address 19067 <1> ;jc short sysstat_gpa1 19068 00003FF9 7294 <1> jc short sysstat_err1 19069 <1> ; 18/10/2015 19070 00003FFB 89C7 <1> mov edi, eax ; physical address 19071 <1> ;mov [u.pcount], cx ; remain bytes in page 19072 <1> ;sysstat_gpa1: 19073 00003FFD C3 <1> retn 19074 <1> 19075 <1> fclose: 19076 <1> ; 12/03/2022 19077 <1> ; 11/02/2022 19078 <1> ; 08/01/2022 19079 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 19080 <1> ; 08/04/2021 19081 <1> ; 04/04/2021 19082 <1> ; 18/08/2020 - Retro UNIX 386 v2 19083 <1> ; 18/06/2015 (Retro UNIX 386 v1 - Beginning) 19084 <1> ; (32 bit offset pointer modification) 19085 <1> ; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1) 19086 <1> ; 19087 <1> ; Given the file descriptor (index to the u.fp list) 19088 <1> ; 'fclose' first gets the i-number of the file via 'getf'. 19089 <1> ; If i-node is active (i-number > 0) the entry in 19090 <1> ; u.fp list is cleared. If all the processes that opened 19091 <1> ; that file close it, then fsp etry is freed and the file 19092 <1> ; is closed. If not a return is taken. 19093 <1> ; If the file has been deleted while open, 'anyi' is called 19094 <1> ; to see anyone else has it open, i.e., see if it is appears 19095 <1> ; in another entry in the fsp table. Upon return from 'anyi' 19096 <1> ; a check is made to see if the file is special. 19097 <1> ; 19098 <1> ; INPUTS -> 19099 <1> ; r1 - contains the file descriptor (value=0,1,2...) 19100 <1> ; u.fp - list of entries in the fsp table 19101 <1> ; fsp - table of entries (4 words/entry) of open files. 19102 <1> ; OUTPUTS -> 19103 <1> ; r1 - contains the same file descriptor 19104 <1> ; r2 - contains i-number 19105 <1> ; 19106 <1> ; ((AX = R1)) 19107 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 19108 <1> ; 19109 <1> ; Retro UNIX 8086 v1 modification : CF = 1 19110 <1> ; if i-number of the file is 0. (error) 19111 <1> 19112 <1> ; 08/04/2021 19113 <1> ; INPUT: 19114 <1> ; eax = file descriptor 19115 <1> ; OUTPUT: 19116 <1> ; cf = 0 -> eax = file descriptor 19117 <1> ; cf = 1 -> file not open ; 11/02/2022 19118 <1> 19119 <1> ; 18/08/2020 19120 <1> ;movzx edx, ax ; ** 19121 00003FFE 89C3 <1> mov ebx, eax 19122 <1> 19123 <1> ; 18/08/2020 19124 <1> _fclose: 19125 00004000 53 <1> push ebx ; *** ; file descriptor (index to u.fp) 19126 <1> 19127 <1> ;push ax ; *** 19128 <1> ; mov r1,-(sp) / put r1 on the stack (it contains 19129 <1> ; / the index to u.fp list) 19130 <1> ; ebx = file descriptor/number 19131 00004001 E840000000 <1> call getf 19132 <1> ; jsr r0,getf / r1 contains i-number, 19133 <1> ; / cdev has device =, u.fofp 19134 <1> ; / points to 3rd word of fsp entry 19135 <1> ;cmp eax, 1 ; 18/08/2020 19136 00004006 6683F801 <1> cmp ax, 1 ; r1 19137 <1> ; tst r1 / is i-number 0? 19138 0000400A 7238 <1> jb short fclose_2 19139 <1> ; beq 1f / yes, i-node not active so return 19140 <1> ; tst (r0)+ / no, jump over error return 19141 <1> 19142 <1> ;mov ebx, edx ; ** 19143 <1> ; 18/08/2020 19144 0000400C 8B1C24 <1> mov ebx, [esp] 19145 <1> ;mov edx, eax 19146 <1> ;;mov dx, ax ; * 19147 <1> ; mov r1,r2 / move i-number to r2 ;* 19148 <1> ; mov (sp),r1 / restore value of r1 from the stack 19149 <1> ; / which is index to u.fp ; ** 19150 0000400F C683[AE6C0000]00 <1> mov byte [ebx+u.fp], 0 19151 <1> ; clrb u.fp(r1) / clear that entry in the u.fp list 19152 00004016 8B1D[B86C0000] <1> mov ebx, [u.fofp] 19153 <1> ; mov u.fofp,r1 / r1 points to 3rd word in fsp entry 19154 <1> 19155 <1> ; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure) 19156 <1> ; ebx = 5th word of fsp entry (64 bit file offset) 19157 <1> fclose_0: 19158 <1> ; 08/01/2022 19159 0000401C FE4BFE <1> dec byte [ebx-2] ; 18/08/2020 - Retro UNIX 386 v2 19160 <1> ;dec byte [ebx+4] ; 18/06/2015 19161 <1> ; decb 2(r1) / decrement the number of processes 19162 <1> ; / that have opened the file 19163 0000401F 7923 <1> jns short fclose_2 ; jump if not negative (jump if bit 7 is 0) 19164 <1> ; bge 1f / if all processes haven't closed the file, return 19165 <1> ; 19166 <1> ;push dx ; * 19167 <1> ; mov r2,-(sp) / put r2 on the stack (i-number) 19168 <1> ;;xor ax, ax ; 0 19169 <1> ;xor eax, eax ; 18/08/2020 19170 <1> ; clear 1st word of fsp entry 19171 <1> ;mov [ebx-8], ax ; 0 ; 18/08/2020 19172 <1> ; 18/08/2020 - Retro UNIX 386 v2 19173 00004021 66C743F80000 <1> mov word [ebx-8], 0 ; clear 1st word of fsp entry ; i-number 19174 <1> ; Note: 32 bit i-node number field is ready but 19175 <1> ; it is not used in current runix version. 19176 <1> 19177 <1> ;;mov [ebx-4], ax ; 0 19178 <1> ; clr -4(r1) / clear 1st word of fsp entry 19179 <1> ;mov al, [ebx+5] ; 18/06/2015 19180 <1> ; ; tstb 3(r1) / has this file been deleted 19181 <1> ;and al, al 19182 <1> ;jz short fclose_1 19183 <1> ; ; beq 2f / no, branch 19184 <1> 19185 <1> ;push edx ; * ; 18/08/2020 19186 <1> ;mov eax, edx ; * ; 18/08/2020 19187 <1> 19188 <1> ;; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure) 19189 <1> ;;test byte [ebx-3], 80h ; open mode & status flags 19190 <1> ; 04/04/2021 - Retro UNIX 386 v2 (new fsp structure) 19191 <1> ;test byte [ebx-4], 80h ; open mode & status flags 19192 <1> ;jz short fclose_1 ; deleted file flag (bit 7) 19193 <1> 19194 <1> ; 04/04/2021 19195 00004027 31D2 <1> xor edx, edx 19196 <1> ; 08/01/2022 19197 00004029 8A53FD <1> mov dl, [ebx-3] ; open mode & status flags 19198 0000402C F6C280 <1> test dl, 80h ; deleted file flag (bit 7) 19199 0000402F 7409 <1> jz short fclose_1 ; (not deleted -while open-) 19200 00004031 52 <1> push edx 19201 <1> ; 12/03/2022 19202 00004032 50 <1> push eax ; inode number 19203 <1> 19204 <1> ; deleted file ! 19205 <1> 19206 <1> ;mov ax, dx ; * 19207 <1> ; mov r2,r1 / yes, put i-number back into r1 19208 <1> ; AX = inode number 19209 00004033 E84E050000 <1> call anyi 19210 <1> ; jsr r0,anyi / free all blocks related to i-number 19211 <1> ; / check if file appears in fsp again 19212 <1> ; 12/03/2022 19213 00004038 58 <1> pop eax ; inode number 19214 <1> ; 04/04/2021 19215 00004039 5A <1> pop edx 19216 <1> ; 11/02/2022 19217 <1> ;(cpu will come here if anyi returns -without error-) 19218 <1> ;; 08/04/2021 19219 <1> ;jc short fclose_3 ; error code in eax 19220 <1> ;; 18/08/2020 19221 <1> ;;jmp short fclose_2 19222 <1> 19223 <1> ; ax = inode number 19224 <1> fclose_1: ; 2: 19225 <1> ; 04/04/2021 19226 0000403A 80E201 <1> and dl, 1 19227 0000403D FEC2 <1> inc dl ; 0 -> 1 (open for read), 1 -> 2 (open for write) 19228 <1> 19229 <1> ;pop eax ; * ; 18/08/2020 19230 <1> ;;pop ax ; * 19231 <1> ; mov (sp)+,r1 / put i-number back into r1 19232 0000403F E814170000 <1> call iclose ; close if it is special file 19233 <1> ; jsr r0,iclose / check to see if it is a special file 19234 <1> ; 11/02/2022 19235 <1> ;(cpu will come here if iclose returns -without error-) 19236 <1> ;; 08/04/2021 19237 <1> ;jnc short fclose_2 19238 <1> ;fclose_3: 19239 <1> ; pop ebx ; *** ; file descriptor 19240 <1> ; ; eax = error code 19241 <1> ; retn 19242 <1> fclose_2: ; 1: 19243 00004044 58 <1> pop eax ; *** ; 18/08/2020 19244 <1> ;pop ax ; *** 19245 <1> ; mov (sp)+,r1 / put index to u.fp back into r1 19246 00004045 C3 <1> retn 19247 <1> ; rts r0 19248 <1> 19249 <1> ; 08/01/2022 19250 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 19251 <1> getf: ; / get the device number and the i-number of an open file 19252 <1> ; 13/05/2015 19253 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 19254 <1> ; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1) 19255 <1> 19256 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 19257 <1> ; 19258 <1> ; 16/05/2021 19259 <1> ; 27/03/2020 - Retro UNIX 386 v2 19260 <1> ; (new open files -fsp- structure) 19261 <1> ; 13/05/2015 19262 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 19263 <1> ; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1) 19264 <1> 19265 <1> ; INPUT: 19266 <1> ; ;eax = file descriptor/number 19267 <1> ; ebx = file descriptor/number ; 18/08/2020 19268 <1> ; OUTPUT: 19269 <1> ; bl = open mode & status flag ; 27/03/2020 19270 <1> ; (bit 0 open mode flag, 0 = read, 1 = write) 19271 <1> ; eax = inode number (in AX) 19272 <1> ; If eax = 0 -> file not open 19273 <1> ; byte [cdev] = logical drive number (of inode in eax) 19274 <1> ; 19275 <1> ; Modified registers: eax, ebx 19276 <1> 19277 <1> ; 16/05/2021 ('getf' procedure, unix v7 x86 'fio.c') 19278 <1> ; /* 19279 <1> ; * Convert a user supplied 19280 <1> ; * file descriptor into a pointer 19281 <1> ; * to a file structure. 19282 <1> ; * Only task is to check range 19283 <1> ; * of the descriptor. 19284 <1> ; */ 19285 <1> ; struct file * 19286 <1> ; getf(f) 19287 <1> ; 19288 <1> ; 18/08/2020 19289 <1> ; ebx = file descriptor/number 19290 <1> 19291 <1> ; 16/05/2021 19292 <1> ;NOFILE equ 10 ; 08/01/2022 19293 <1> 19294 <1> ; 18/08/2020 19295 <1> ;mov ebx, eax 19296 <1> getf1: ;; Calling point from 'rw1' (23/05/2013) 19297 <1> 19298 <1> ; ebx = file descriptor/number 19299 <1> 19300 <1> ; 18/08/2020 19301 00004046 29C0 <1> sub eax, eax ; eax = 0 19302 <1> 19303 00004048 83FB0A <1> cmp ebx, 10 ; cmp ebx, NOFILE ; 16/05/2021 19304 <1> ; cmp r1,$10. / user limited to 10 open files 19305 0000404B 732E <1> jnb short getf2 ; 13/05/2015 19306 <1> ;jnb error 19307 <1> ; bhis error3 / u.fp is table of users open files, 19308 <1> ; / index in fsp table 19309 <1> ; 08/01/2022 19310 0000404D 8A83[AE6C0000] <1> mov al, [ebx+u.fp] 19311 <1> ;mov bl, [ebx+u.fp] 19312 <1> ; movb u.fp(r1),r1 / r1 contains number of entry 19313 <1> ; / in fsp table 19314 00004053 08C0 <1> or al, al ; 08/01/2022 19315 <1> ;or bl, bl 19316 <1> ;jnz short getf3 19317 00004055 7424 <1> jz short getf2 ; 18/08/2020 19318 <1> ;;jz short getf4 19319 <1> ; beq 1f / if its zero return 19320 <1> ;getf2: 19321 <1> ; ; 'File not open !' error (ax=0) 19322 <1> ; ;sub eax, eax ; 18/08/2020 19323 <1> ; retn 19324 <1> ;getf3: 19325 <1> ; Retro UNIX 386 v1 modification ! (11/05/2015) 19326 <1> ; 19327 <1> ; 'fsp' table (10 bytes/entry) 19328 <1> ; bit 15 bit 0 19329 <1> ; ---|------------------------------------------- 19330 <1> ; r/w| i-number of open file 19331 <1> ; ---|------------------------------------------- 19332 <1> ; device number 19333 <1> ; ----------------------------------------------- 19334 <1> ; offset pointer, r/w pointer to file (bit 0-15) 19335 <1> ; ----------------------------------------------- 19336 <1> ; offset pointer, r/w pointer to file (bit 16-31) 19337 <1> ; ----------------------|------------------------ 19338 <1> ; flag that says file | number of processes 19339 <1> ; has been deleted | that have file open 19340 <1> ; ----------------------|------------------------ 19341 <1> 19342 <1> ; Retro UNIX 386 v2 modification ! (27/03/2020) 19343 <1> 19344 <1> ; bit 15 bit 0 19345 <1> ; ----------------------------------------------- byte 0 19346 <1> ; i-number of open file 19347 <1> ; ----------------------------------------------- byte 2 19348 <1> ; high word of 32 bit i-number 19349 <1> ; ----------------------------------------------- byte 4 19350 <1> ; open mode & status | device number 19351 <1> ; ----------------------------------------------- byte 6 19352 <1> ; reserved byte | open count 19353 <1> ; ----------------------------------------------- byte 8 19354 <1> ; offset pointer, i.e., r/w pointer to file 19355 <1> ; ----------------------------------------------- byte 10 19356 <1> ; 64 bit file offset pointer (bit 16-31) 19357 <1> ; ----------------------------------------------- byte 12 19358 <1> ; 64 bit file offset pointer (bit 32-47) 19359 <1> ; ----------------------------------------------- byte 14 19360 <1> ; 64 bit file offset pointer (bit 48-63) 19361 <1> ; ----------------------------------------------- byte 16 19362 <1> 19363 <1> ; 11/05/2015 - Retro UNIX 386 v1 19364 <1> ;mov eax, 10 19365 <1> 19366 <1> ; 27/03/2020 - Retro UNIX 386 v2 19367 <1> ;mov eax, opfls.size ; mov eax, 16 19368 <1> 19369 <1> ;sub eax, eax ; 18/08/2020 ; eax = 0 19370 <1> 19371 <1> ;mov al, opfls.size ; mov al, 16 19372 <1> ; 19373 <1> ;mul bl 19374 <1> ;;mov ebx, fsp-6 ; the 3rd word in the fsp entry 19375 <1> ;; 27/03/2020 19376 <1> ;mov ebx, fsp-(opfls.size-opfls.offset) ; fsp-8 19377 <1> 19378 <1> ;add ebx, eax 19379 <1> ; asl r1 19380 <1> ; asl r1 / multiply by 8 to get index into 19381 <1> ; / fsp table entry 19382 <1> ; asl r1 19383 <1> ; add $fsp-4,r1 / r1 is pointing at the 3rd word 19384 <1> ; / in the fsp entry 19385 <1> ; 08/01/2022 19386 00004057 88C3 <1> mov bl, al 19387 <1> ; 18/08/2020 19388 00004059 FECB <1> dec bl ; zero based fsp table entry number 19389 <1> ;shl bl, 4 ; * 16 ; opfls.size 19390 <1> ; 08/01/2022 19391 0000405B C1E304 <1> shl ebx, 4 ; * 16 ; opfls.size 19392 0000405E 81C3[1C690000] <1> add ebx, fsp+8 ; opfls.offset 19393 <1> ; ebx = address of the file offset pointer 19394 <1> ; (not file offset! not fsp entry address !) 19395 <1> 19396 00004064 891D[B86C0000] <1> mov [u.fofp], ebx 19397 <1> ; mov r1,u.fofp / save address of 3rd word 19398 <1> ; / in fsp entry in u.fofp 19399 <1> ; 18/08/2020 19400 0000406A 8A43FD <1> mov al, [ebx-3] ; open mode & status flags 19401 <1> 19402 0000406D 50 <1> push eax 19403 <1> 19404 <1> ;mov ax, [ebx] 19405 <1> ;;mov [cdev], al ; ;;Retro UNIX 8086 v1 ! 19406 <1> ;mov [cdev], ax ; ;;in fact (!) 19407 <1> ;;dev number is in 1 byte 19408 <1> ; mov -(r1),cdev / remove the device number cdev 19409 <1> 19410 <1> ; 18/08/2020 19411 0000406E 8A43FC <1> mov al, [ebx-4] ; logical drive number 19412 <1> 19413 00004071 A2[816C0000] <1> mov [cdev], al 19414 <1> 19415 <1> ;dec ebx 19416 <1> ;dec ebx 19417 <1> ; 18/08/2020 19418 00004076 668B43F8 <1> mov ax, [ebx-8] 19419 <1> ; mov -(r1),r1 / and the i-number r1 19420 <1> 19421 0000407A 5B <1> pop ebx ; ebx = bl = open mode and status flag 19422 <1> ; (bit 0 is open mode flag, 0 = read, 1 = write) 19423 <1> ; eax = inode number (in ax) 19424 <1> 19425 <1> getf2: ; 18/08/2020 19426 <1> getf4: ; 1: ; 08/01/2022 19427 0000407B C3 <1> retn 19428 <1> ; rts r0 19429 <1> 19430 <1> ; 15/05/2022 19431 <1> ; 08/01/2022 19432 <1> ; 19/12/2021 19433 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 19434 <1> namei: 19435 <1> ; 18/10/2021 19436 <1> ; 12/06/2021 19437 <1> ; 01/05/2021 19438 <1> ; 26/03/2021 19439 <1> ; 25/03/2021 (Retro UNIX 386 v2 - Beginning) 19440 <1> ; 04/12/2015 (14 byte file names) 19441 <1> ; 18/10/2015 (nbase, ncount) 19442 <1> ; 12/10/2015 19443 <1> ; 21/08/2015 19444 <1> ; 18/07/2015 19445 <1> ; 02/07/2015 19446 <1> ; 17/06/2015 19447 <1> ; 16/06/2015 (Retro UNIX 386 v1 - Beginning) 19448 <1> ; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 19449 <1> ; 19450 <1> ; 'namei' takes a file path name and returns i-number of 19451 <1> ; the file in the current directory or the root directory 19452 <1> ; (if the first character of the pathname is '/'). 19453 <1> ; 19454 <1> ; INPUTS -> 19455 <1> ; u.namep - points to a file path name 19456 <1> ; u.cdir - i-number of users directory 19457 <1> ; u.cdev - device number on which user directory resides 19458 <1> ; OUTPUTS -> 19459 <1> ; r1 - i-number of file 19460 <1> ; cdev 19461 <1> ; u.dirbuf - points to directory entry where a match 19462 <1> ; occurs in the search for file path name. 19463 <1> ; If no match u.dirp points to the end of 19464 <1> ; the directory and r1 = i-number of the current 19465 <1> ; directory. 19466 <1> ; ((AX = R1)) 19467 <1> ; 19468 <1> ; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM) 19469 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 19470 <1> ; 19471 <1> 19472 <1> ;mov ax, [u.cdir] 19473 <1> ; mov u.cdir,r1 / put the i-number of current directory 19474 <1> ; / in r1 19475 <1> ; 01/05/2021 19476 0000407C A1[A86C0000] <1> mov eax, [u.cdir] 19477 00004081 8A15[AC6C0000] <1> mov dl, [u.cdrv] 19478 00004087 8815[816C0000] <1> mov [cdev], dl 19479 <1> ;mov dx, [u.cdrv] 19480 <1> ;mov [cdev], dx ; NOTE: Retro UNIX 8086 v1 19481 <1> ; device/drive number is in 1 byte, 19482 <1> ; not in 1 word! 19483 <1> ; mov u.cdev,cdev / device number for users directory 19484 <1> ; / into cdev 19485 <1> ; 12/10/2015 19486 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 19487 <1> ; convert virtual (pathname) addr to physical address 19488 0000408D E849010000 <1> call trans_addr_nmbp ; 12/10/2015 19489 <1> ; esi = physical address of [u.namep] 19490 <1> ; ecx = byte count in the page 19491 00004092 803E2F <1> cmp byte [esi], '/' 19492 <1> ; cmpb *u.namep,$'/ / is first char in file name a / 19493 00004095 751C <1> jne short namei_1 19494 <1> ; bne 1f 19495 00004097 FF05[C06C0000] <1> inc dword [u.namep] 19496 <1> ; inc u.namep / go to next char 19497 <1> ;dec cx ; remain byte count in the page 19498 0000409D 49 <1> dec ecx ; 18/10/2021 19499 0000409E 7506 <1> jnz short namei_0 19500 <1> ; 12/10/2015 19501 000040A0 E836010000 <1> call trans_addr_nmbp ; convert virtual address to physical 19502 <1> ; esi = physical address (page start + offset) 19503 <1> ; ecx = byte count in the page 19504 000040A5 4E <1> dec esi 19505 <1> namei_0: 19506 000040A6 46 <1> inc esi ; go to next char 19507 <1> ;mov ax, [rootdir] ; 09/07/2013 19508 <1> ; 18/10/2021 19509 000040A7 A1[866C0000] <1> mov eax, [rootdir] 19510 <1> ; mov rootdir,r1 / put i-number of rootdirectory in r1 19511 000040AC C605[816C0000]00 <1> mov byte [cdev], 0 19512 <1> ; clr cdev / clear device number 19513 <1> namei_1: ; 1: 19514 000040B3 F606FF <1> test byte [esi], 0FFh 19515 <1> ;jz short getf4 19516 <1> ; 26/03/2021 19517 <1> ;jz short getf2 ; retn 19518 <1> ;;jz nig 19519 <1> ; tstb *u.namep / is the character in file name a nul 19520 <1> ; beq nig / yes, end of file name reached; 19521 <1> ; / branch to "nig" 19522 <1> ; 19/12/2021 19523 <1> namei_9: 19524 <1> ; 12/06/2021 19525 <1> ;jnz short namei_2 19526 <1> ;retn 19527 <1> ; 08/01/2022 19528 000040B6 74C3 <1> jz short getf4 19529 <1> namei_2: ; 1: 19530 <1> ; 18/10/2015 19531 000040B8 8935[286D0000] <1> mov [nbase], esi 19532 <1> ;mov [ncount], cx 19533 <1> ; 18/10/2021 19534 000040BE 890D[2C6D0000] <1> mov [ncount], ecx 19535 <1> ; 19536 <1> ;;mov dx, 2 19537 <1> ;mov dl, 2 ; user flag (read, non-owner) 19538 <1> ; 25/03/2021 19539 <1> ;mov dx, 100h ; IREAD - read, owner 19540 <1> ; 18/10/2021 19541 000040C4 29D2 <1> sub edx, edx 19542 000040C6 FEC6 <1> inc dh ; dx = 100h ; IREAD - read, owner 19543 000040C8 E8920B0000 <1> call access 19544 <1> ; jsr r0,access; 2 / get i-node with i-number r1 19545 <1> ; 'access' will not return here if user has not "r" permission ! 19546 <1> 19547 <1> ;test word [i.flgs], 4000h 19548 <1> ; ; bit $40000,i.flgs / directory i-node? 19549 <1> ;jz short namei_err 19550 <1> ; beq error3 / no, got an error 19551 <1> ; 26/03/2021 19552 <1> ; mov al, [i.flgs+1] 19553 <1> ; ;test al, 80h ; IFREG ; 80h 19554 <1> ; ;jz short namei_err ; not a regular file ! (device!?) 19555 <1> ; ;and al, 40h ; IFDIR ; 40h 19556 <1> ; ;jz short namei_err ; not a sub directory ! 19557 <1> ; shl al, 1 ; 80h (IFREG flag) -> cf = 1 19558 <1> ; jnc short namei_err ; not a regular file ! (device!?) 19559 <1> ; shl al, 1 ; 80h (IFDIR flag) -> cf = 1 19560 <1> ; jnc short namei_err ; not a sub directory ! 19561 <1> 19562 <1> ; 27/03/2021 19563 000040CD E83A010000 <1> call chk_dir ; check for directory, jump to 'error' if not 19564 <1> ; CPU will be here if the inode is a (valid) directory inode 19565 <1> 19566 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 19567 <1> ;xor eax, eax 19568 <1> ;mov [u.off], eax ; 0 19569 <1> ; 01/05/2021 - Retro UNIX 386 v2 inode structure 19570 000040D2 A1[2C680000] <1> mov eax, [i.size] 19571 <1> ;mov ax, [i.size] 19572 000040D7 A3[BC6C0000] <1> mov [u.dirp], eax 19573 <1> ; mov i.size,u.dirp / put size of directory in u.dirp 19574 <1> ; clr u.off / u.off is file offset used by user 19575 <1> ; 18/10/2021 19576 000040DC 31C0 <1> xor eax, eax 19577 <1> ;mov [u.off], eax ; 0 19578 000040DE BB[C46C0000] <1> mov ebx, u.off 19579 000040E3 8903 <1> mov [ebx], eax ; mov dword [u.off], 0 19580 <1> ; 19581 000040E5 891D[B86C0000] <1> mov [u.fofp], ebx ; u.off ; 18/10/2021 19582 <1> ;mov dword [u.fofp], u.off 19583 <1> ; mov $u.off,u.fofp / u.fofp is a pointer to 19584 <1> ; / the offset portion of fsp entry 19585 <1> namei_3: ; 2: 19586 000040EB C705[C86C0000]- <1> mov dword [u.base], u.dirbuf 19587 000040F1 [DC6C0000] <1> 19588 <1> ; mov $u.dirbuf,u.base / u.dirbuf holds a file name 19589 <1> ; / copied from a directory 19590 000040F5 C705[CC6C0000]1000- <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 19591 000040FD 0000 <1> 19592 <1> ; mov $10.,u.count / u.count is byte count 19593 <1> ; / for reads and writes 19594 <1> ;mov ax, [ii] 19595 <1> ; 18/10/2021 19596 000040FF A1[7C6C0000] <1> mov eax, [ii] ; (32 bit inode number) 19597 <1> ; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall') 19598 00004104 FE05[166D0000] <1> inc byte [u.kcall] ; the caller is 'namei' sign 19599 0000410A E8D20D0000 <1> call readi 19600 <1> ; jsr r0,readi / read 10. bytes of file 19601 <1> ; with i-number (r1); i.e. read a directory entry 19602 <1> 19603 0000410F 8B0D[D06C0000] <1> mov ecx, [u.nread] 19604 00004115 09C9 <1> or ecx, ecx 19605 <1> ; tst u.nread 19606 00004117 741A <1> jz short nib 19607 <1> ; ble nib / gives error return 19608 <1> ; 19609 <1> ;mov bx, [u.dirbuf] 19610 <1> ;and bx, bx 19611 <1> ; 18/10/2021 19612 00004119 66F705[DC6C0000]FF- <1> test word [u.dirbuf], 0FFFFh 19613 00004121 FF <1> 19614 <1> ; tst u.dirbuf / 19615 00004122 7513 <1> jnz short namei_4 19616 <1> ; bne 3f / branch when active directory entry 19617 <1> ; / (i-node word in entry non zero) 19618 00004124 A1[C46C0000] <1> mov eax, [u.off] 19619 00004129 83E810 <1> sub eax, 16 ; 04/12/2015 (10 -> 16) 19620 0000412C A3[BC6C0000] <1> mov [u.dirp], eax 19621 <1> ; mov u.off,u.dirp 19622 <1> ; sub $10.,u.dirp 19623 00004131 EBB8 <1> jmp short namei_3 19624 <1> ; br 2b 19625 <1> 19626 <1> ; 18/07/2013 19627 <1> nib: 19628 00004133 31C0 <1> xor eax, eax ; xor ax, ax ; ax = 0 -> file not found 19629 00004135 F9 <1> stc 19630 <1> nig: 19631 00004136 C3 <1> retn 19632 <1> 19633 <1> ; 27/03/2021 19634 <1> ;namei_err: 19635 <1> ; 16/06/2015 19636 <1> ; mov dword [u.error], ERR_NOT_DIR ; 'not a directory !' error 19637 <1> ; jmp error 19638 <1> 19639 <1> namei_4: ; 3: 19640 <1> ; 18/10/2015 19641 <1> ; 12/10/2015 19642 <1> ; 21/08/2015 19643 <1> ; 18/07/2015 19644 00004137 8B2D[C06C0000] <1> mov ebp, [u.namep] 19645 <1> ; mov u.namep,r2 / u.namep points into a file name string 19646 0000413D BF[DE6C0000] <1> mov edi, u.dirbuf + 2 19647 <1> ; mov $u.dirbuf+2,r3 / points to file name of directory entry 19648 <1> ; 18/10/2015 19649 00004142 8B35[286D0000] <1> mov esi, [nbase] 19650 <1> ;mov cx, [ncount] 19651 <1> ;and cx, cx 19652 <1> ; 18/10/2021 19653 00004148 8B0D[2C6D0000] <1> mov ecx, [ncount] 19654 0000414E 21C9 <1> and ecx, ecx 19655 00004150 7505 <1> jnz short namei_5 19656 <1> ; 19657 00004152 E88A000000 <1> call trans_addr_nm ; convert virtual address to physical 19658 <1> ; esi = physical address (page start + offset) 19659 <1> ; ecx = byte count in the page 19660 <1> namei_5: ; 3: 19661 00004157 45 <1> inc ebp ; 18/07/2015 19662 00004158 AC <1> lodsb ; mov al, [esi] ; inc esi (al = r4) 19663 <1> ; movb (r2)+,r4 / move a character from u.namep string into r4 19664 00004159 08C0 <1> or al, al 19665 0000415B 741C <1> jz short namei_7 19666 <1> ; beq 3f / if char is nul, then the last char in string 19667 <1> ; / has been moved 19668 0000415D 3C2F <1> cmp al, '/' 19669 <1> ; cmp r4,$'/ / is char a 19670 0000415F 7418 <1> je short namei_7 19671 <1> ; beq 3f 19672 <1> ; 12/10/2015 19673 <1> ;dec cx ; remain byte count in the page 19674 00004161 49 <1> dec ecx ; 18/10/2021 19675 00004162 7505 <1> jnz short namei_6 19676 00004164 E878000000 <1> call trans_addr_nm ; convert virtual address to physical 19677 <1> ; esi = physical address (page start + offset) 19678 <1> ; ecx = byte count in the page 19679 <1> namei_6: 19680 00004169 81FF[EC6C0000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 19681 <1> ; cmp r3,$u.dirbuf+10. / have I checked 19682 <1> ; / all 8 bytes of file name 19683 0000416F 74E6 <1> je short namei_5 19684 <1> ; beq 3b 19685 00004171 AE <1> scasb 19686 <1> ; cmpb (r3)+,r4 / compare char in u.namep string to file name 19687 <1> ; / char read from directory 19688 00004172 74E3 <1> je short namei_5 19689 <1> ; beq 3b / branch if chars match 19690 <1> namei_10: 19691 00004174 E972FFFFFF <1> jmp namei_3 ; 2b 19692 <1> ; br 2b / file names do not match go to next directory entry 19693 <1> namei_7: ; 3: 19694 00004179 81FF[EC6C0000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 19695 <1> ; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched 19696 0000417F 7405 <1> je short namei_8 19697 <1> ; beq 3f 19698 <1> ;mov ah, [edi] 19699 <1> ;;inc edi 19700 <1> ;and ah, ah 19701 <1> ; ; tstb (r3)+ / 19702 <1> ; 18/10/2021 19703 00004181 F607FF <1> test byte [edi], 0FFh 19704 <1> ; 08/01/2021 19705 00004184 75EE <1> jnz short namei_10 19706 <1> ;jnz namei_3 19707 <1> ; bne 2b 19708 <1> namei_8: ; 3 19709 00004186 892D[C06C0000] <1> mov [u.namep], ebp ; 18/07/2015 19710 <1> ; mov r2,u.namep / u.namep points to char 19711 <1> ; / following a / or nul 19712 <1> ;mov bx, [u.dirbuf] 19713 <1> ; mov u.dirbuf,r1 / move i-node number in directory 19714 <1> ; / entry to r1 19715 <1> 19716 <1> ;;;; 19717 <1> ; 15/05/2022 - Retro UNIX (8086/386) feature only ! 19718 <1> ; ! 'pwd' utility modification ! 19719 <1> ; ((if directory entry name is a dotdot))) 19720 <1> ;; check if it is mounted device's root directory inode 19721 <1> ; and if so, replace it with parent dir inode number 19722 <1> ; of mounting directory in [mntp]. 19723 <1> 19724 0000418C 0FB71D[DC6C0000] <1> movzx ebx, word [u.dirbuf] 19725 <1> 19726 00004193 6683FB01 <1> cmp bx, 1 ; root directory inode number 19727 00004197 7539 <1> jne short namei_11 19728 <1> 19729 00004199 3B1D[7C6C0000] <1> cmp ebx, [ii] ; for root dir, '.' & '..' is 1 19730 0000419F 7531 <1> jne short namei_11 ; not root dir (of mounted dev) 19731 <1> 19732 <1> ;cmp [idev], bh ; 0 19733 000041A1 383D[816C0000] <1> cmp [cdev], bh ; 0 19734 <1> ; 0 = root fs, dev num in [rdev] 19735 <1> ; 1 = mounted, dev num in [mdev] 19736 000041A7 7629 <1> jna short namei_11 19737 <1> 19738 <1> ; dotdot (parent directory link) check 19739 000041A9 66813D[DE6C0000]2E- <1> cmp word [u.dirbuf+2], '..' 19740 000041B1 2E <1> 19741 000041B2 751E <1> jne short namei_11 19742 000041B4 803D[E06C0000]00 <1> cmp byte [u.dirbuf+4], 0 19743 000041BB 7515 <1> jne short namei_11 19744 <1> 19745 <1> ; (This may not be necessary because [idev] = 1 19746 <1> ; and [mnti] is expected as a sub dir inode number) 19747 000041BD 391D[8A6C0000] <1> cmp [mnti], ebx ; 1 19748 000041C3 760D <1> jna short namei_11 19749 <1> 19750 <1> ; change inumber to parent dir inum of mount directory 19751 000041C5 8B1D[8E6C0000] <1> mov ebx, [mntp] 19752 000041CB C605[816C0000]00 <1> mov byte [cdev], 0 ; root fs 19753 <1> namei_11: 19754 <1> ;;;; 19755 <1> 19756 000041D2 20C0 <1> and al, al 19757 <1> ; tst r4 / if r4 = 0 the end of file name reached, 19758 <1> ; / if r4 = then go to next directory 19759 <1> ; 15/05/2022 19760 000041D4 89D8 <1> mov eax, ebx 19761 <1> ;;mov ax, bx 19762 <1> ;;mov ax, [u.dirbuf] ; 17/06/2015 19763 <1> ;; 18/10/2021 (16 bit inode number in 32 bit register) 19764 <1> ;movzx eax, word [u.dirbuf] 19765 <1> ; 19/12/2021 19766 000041D6 E9DBFEFFFF <1> jmp namei_9 ; eax = inode number 19767 <1> ; jnz namei_2 19768 <1> ; ; bne 1b 19769 <1> ; ; AX = i-number of the file 19770 <1> ;;;nig: 19771 <1> ; retn 19772 <1> ; tst (r0)+ / gives non-error return 19773 <1> ;;nib: 19774 <1> ;; xor ax, ax ; Retro UNIX 8086 v1 modification ! 19775 <1> ; ax = 0 -> file not found 19776 <1> ;; stc ; 27/05/2013 19777 <1> ;; retn 19778 <1> ; rts r0 19779 <1> 19780 <1> trans_addr_nmbp: 19781 <1> ; 18/10/2021 - Retro UNIX 386 v2 19782 <1> ; 18/10/2015 19783 <1> ; 12/10/2015 19784 000041DB 8B2D[C06C0000] <1> mov ebp, [u.namep] 19785 <1> trans_addr_nm: 19786 <1> ; 18/10/2021 - Retro UNIX 386 v2 19787 <1> ; Convert virtual (pathname) address to physical address 19788 <1> ; (Retro UNIX 386 v1 feature only !) 19789 <1> ; 18/10/2015 19790 <1> ; 12/10/2015 (u.pnbase & u.pncount has been removed from code) 19791 <1> ; 02/07/2015 19792 <1> ; 17/06/2015 19793 <1> ; 16/06/2015 19794 <1> ; 19795 <1> ; INPUTS: 19796 <1> ; ebp = pathname address (virtual) ; [u.namep] 19797 <1> ; [u.pgdir] = user's page directory 19798 <1> ; OUTPUT: 19799 <1> ; esi = physical address of the pathname 19800 <1> ; ecx = remain byte count in the page 19801 <1> ; 19802 <1> ; (Modified registers: EBX, ECX, EDX, ESI) ; 18/10/2021 19803 <1> ; 19804 <1> 19805 <1> ; 18/10/2021 19806 000041E1 29C9 <1> sub ecx, ecx 19807 <1> ; 19808 <1> ;cmp dword [u.ppgdir], 0 ; /etc/init ? (sysexec) 19809 000041E3 390D[086D0000] <1> cmp [u.ppgdir], ecx ; 0 ; 18/10/2021 19810 000041E9 7618 <1> jna short trans_addr_nmk ; the caller is os kernel; 19811 <1> ; it is already physical address 19812 000041EB 50 <1> push eax 19813 000041EC 89EB <1> mov ebx, ebp ; [u.namep] ; pathname address (virtual) 19814 000041EE E8D4E5FFFF <1> call get_physical_addr ; get physical address 19815 000041F3 7204 <1> jc short tr_addr_nm_err 19816 <1> ; 18/10/2015 19817 <1> ; eax = physical address 19818 <1> ; ecx = remain byte count in page (1-4096) ; 18/10/2021 19819 <1> ; 12/10/2015 (cx = [u.pncount]) 19820 000041F5 89C6 <1> mov esi, eax ; 12/10/2015 (esi=[u.pnbase]) 19821 000041F7 58 <1> pop eax 19822 000041F8 C3 <1> retn 19823 <1> 19824 <1> tr_addr_nm_err: 19825 000041F9 A3[186D0000] <1> mov [u.error], eax 19826 <1> ;pop eax 19827 000041FE E962EFFFFF <1> jmp error 19828 <1> 19829 <1> trans_addr_nmk: 19830 <1> ; 12/10/2015 19831 <1> ; 02/07/2015 19832 00004203 8B35[C06C0000] <1> mov esi, [u.namep] ; [u.pnbase] 19833 <1> ;mov cx, PAGE_SIZE ; 4096 ; [u.pncount] 19834 <1> ; 18/10/2021 19835 00004209 B510 <1> mov ch, PAGE_SIZE/256 19836 0000420B C3 <1> retn 19837 <1> 19838 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 19839 <1> chk_dir: 19840 <1> ; 12/06/2021 19841 <1> ; 27/03/2021 (Retro UNIX 386 v2) 19842 <1> ; Check for directory inode 19843 <1> 19844 0000420C 8A0D[25680000] <1> mov cl, [i.flgs+1] 19845 <1> ;test cl, 80h ; IFREG ; 80h 19846 <1> ;jz short chk_dir_err ; not a regular file ! (device!?) 19847 <1> ;and cl, 40h ; IFDIR ; 40h 19848 <1> ;jz short chk_dir_err ; not a sub directory ! 19849 00004212 D0E1 <1> shl cl, 1 ; 80h (IFREG flag) -> cf = 1 19850 00004214 7305 <1> jnc short chk_dir_err ; not a regular file ! (device!?) 19851 00004216 D0E1 <1> shl cl, 1 ; 40h (IFDIR flag) -> cf = 1 19852 00004218 7301 <1> jnc short chk_dir_err ; not a sub directory ! 19853 <1> ; 12/06/2021 19854 0000421A C3 <1> retn 19855 <1> chk_dir_err: 19856 0000421B C705[186D0000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 19857 00004223 0000 <1> 19858 00004225 E93BEFFFFF <1> jmp error 19859 <1> 19860 <1> ; 06/02/2022 19861 <1> ; 08/01/2022 19862 <1> ; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode) 19863 <1> syschdir: 19864 <1> ; / makes the directory specified in the argument 19865 <1> ; / the current directory 19866 <1> ; 19867 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 19868 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 19869 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 19870 <1> ; 19871 <1> ; 'syschdir' makes the directory specified in its argument 19872 <1> ; the current working directory. 19873 <1> ; 19874 <1> ; Calling sequence: 19875 <1> ; syschdir; name 19876 <1> ; Arguments: 19877 <1> ; name - address of the path name of a directory 19878 <1> ; terminated by nul byte. 19879 <1> ; Inputs: - 19880 <1> ; Outputs: - 19881 <1> ; ............................................................... 19882 <1> ; 19883 <1> ; Retro UNIX 8086 v1 modification: 19884 <1> ; The user/application program puts address of 19885 <1> ; the path name in BX register as 'syschdir' 19886 <1> ; system call argument. 19887 <1> 19888 0000422A 891D[C06C0000] <1> mov [u.namep], ebx 19889 <1> ;jsr r0,arg; u.namep / u.namep points to path name 19890 00004230 E847FEFFFF <1> call namei 19891 <1> ; jsr r0,namei / find its i-number 19892 <1> ;jc error 19893 <1> ; br error3 19894 00004235 730F <1> jnc short syschdir0 19895 <1> ; 'directory not found !' error 19896 00004237 C705[186D0000]0C00- <1> mov dword [u.error], ERR_DIR_NOT_FOUND ; 12 19897 0000423F 0000 <1> 19898 00004241 E91FEFFFFF <1> jmp error 19899 <1> syschdir0: 19900 <1> ; 08/01/2022 19901 00004246 66BA0001 <1> mov dx, 100h ; read access ; IREAD (100h) 19902 0000424A E8100A0000 <1> call access 19903 <1> ; jsr r0,access; 2 / get i-node into core 19904 <1> 19905 <1> ; 06/02/2022 19906 <1> ;; 01/01/2022 (runix v2 fs inode flag) 19907 <1> ;test byte [i.flgs+1], 80h ; regular file ? 19908 <1> ;jz short syschdir2 ; no, error! 19909 <1> ;test byte [i.flgs+1], 40h ; directory flag ? 19910 <1> ;;test word [i.flgs], 4000h 19911 <1> ; ; bit $40000,i.flgs / is it a directory? 19912 <1> ;;jz error 19913 <1> ; ; beq error3 / no error 19914 <1> ;jnz short syschdir1 19915 <1> ;syschdir2: 19916 <1> ;mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 19917 <1> ;jmp error 19918 <1> 19919 <1> ; 06/02/2022 19920 <1> ; check for directory, jump to 'error' if not 19921 0000424F E8B8FFFFFF <1> call chk_dir 19922 <1> ; (cpu will not return here 19923 <1> ; if the inode it is not a valid dir inode) 19924 <1> 19925 <1> syschdir1: 19926 00004254 66A3[A86C0000] <1> mov [u.cdir], ax 19927 <1> ; mov r1,u.cdir / move i-number to users 19928 <1> ; / current directory 19929 <1> ;mov ax, [cdev] 19930 <1> ;mov [u.cdrv], ax 19931 <1> ; 08/01/2022 19932 0000425A A0[816C0000] <1> mov al, [cdev] 19933 0000425F A2[AC6C0000] <1> mov [u.cdrv], al 19934 <1> ; mov cdev,u.cdev / move its device to users 19935 <1> ; / current device 19936 00004264 E91CEFFFFF <1> jmp sysret 19937 <1> ; br sysret3 19938 <1> 19939 <1> syschmod: ; < change mode of file > 19940 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 19941 <1> ; 01/05/2021 19942 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 19943 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 19944 <1> ; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1) 19945 <1> ; 19946 <1> ; 'syschmod' changes mode of the file whose name is given as 19947 <1> ; null terminated string pointed to by 'name' has it's mode 19948 <1> ; changed to 'mode'. 19949 <1> ; 19950 <1> ; Calling sequence: 19951 <1> ; syschmod; name; mode 19952 <1> ; Arguments: 19953 <1> ; name - address of the file name 19954 <1> ; terminated by null byte. 19955 <1> ; mode - (new) mode/flags < attributes > 19956 <1> ; 19957 <1> ; Inputs: - 19958 <1> ; Outputs: - 19959 <1> ; ............................................................... 19960 <1> ; 19961 <1> ; Retro UNIX 8086 v1 modification: 19962 <1> ; 'syschmod' system call has two arguments; so, 19963 <1> ; * 1st argument, name is pointed to by BX register 19964 <1> ; * 2nd argument, mode is in CX register 19965 <1> ; 19966 <1> ; Mode bits (Flags): 19967 <1> ; bit 15 - 'i-node is allocated' flag (8000h) 19968 <1> ; bit 14 - directory flag (4000h) 19969 <1> ; bit 13 - file has modified flag (always on) (2000h) 19970 <1> ; bit 12 - large file flag (1000h) 19971 <1> ; bit 6,7,8,9,10,11 are not used (undefined) 19972 <1> ; bit 5 - set user ID on execution flag (20h) 19973 <1> ; bit 4 - executable flag (10h) 19974 <1> ; bit 3 - read permission for owner (08h) 19975 <1> ; bit 2 - write permission for owner (04h) 19976 <1> ; bit 1 - read permission for non-owner (02h) 19977 <1> ; bit 0 - write permission for non-owner (01h) 19978 <1> 19979 <1> ; 01/05/2021 (07/02/2020) 19980 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files 19981 <1> ; bit 15 - IFREG - regular file (8000h) 19982 <1> ; bit 14 - IFDIR - directory (4000h) 19983 <1> ; bit 13 - IRSVD - 0 - reserved/mounted bit (2000h) 19984 <1> ; bit 12 - ILARG - large file addressing bit (1000h) 19985 <1> ; bit 11 - ISUID - set user id on exec (800h) 19986 <1> ; bit 10 - ISGID - set group id on exec (400h) 19987 <1> ; bit 9 - IEXTT - 0 - use extents (200h) 19988 <1> ; bit 8 - IREAD - read, owner (100h) 19989 <1> ; bit 7 - IWRITE - write, owner (80h) 19990 <1> ; bit 6 - IEXEC - execute, owner (40h) 19991 <1> ; bit 5 - read, group (20h) 19992 <1> ; bit 4 - write, group (10h) 19993 <1> ; bit 3 - execute, group (08h) 19994 <1> ; bit 2 - read, others (04h) 19995 <1> ; bit 1 - write, others (02h) 19996 <1> ; bit 0 - execute, others (01h) 19997 <1> ; 19998 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices 19999 <1> ; bit 15 - IFREG - 0 - device file (8000h) 20000 <1> ; bit 14 - IFBLK - block device (4000h) 20001 <1> ; bit 13 - IFCHR - 1 - character special (2000h) 20002 <1> ; bit 12 - IFIFO - fifo special (1000h) 20003 <1> ; bit 11 - IPIPE - pipe special (800h) 20004 <1> ; bit 10 - IREDIR - redirected (400h) 20005 <1> ; bit 9 - IEXTR - external device driver (200h) 20006 <1> ; bit 8 - IREAD - read, owner (100h) 20007 <1> ; bit 7 - IWRITE - write, owner (80h) 20008 <1> ; bit 6 - IEXEC - execute, owner (40h) 20009 <1> ; bit 5 - read, group (20h) 20010 <1> ; bit 4 - write, group (10h) 20011 <1> ; bit 3 - execute, group (08h) 20012 <1> ; bit 2 - read, others (04h) 20013 <1> ; bit 1 - write, others (02h) 20014 <1> ; bit 0 - execute, others (01h) 20015 <1> 20016 <1> ; / name; mode 20017 00004269 E877000000 <1> call isown 20018 <1> ; jsr r0,isown / get the i-node and check user status 20019 <1> 20020 <1> ; 25/05/2020 20021 <1> ; AL = new mode (return form 'isown', ecx -> eax) 20022 <1> 20023 <1> ;test word [i.flgs], 4000h 20024 <1> ; ; bit $40000,i.flgs / directory? 20025 <1> ;jz short syschmod1 20026 <1> ; ; beq 2f / no 20027 <1> ;; AL = (new) mode 20028 <1> ;and al, 0CFh ; 11001111b (clears bit 4 & 5) 20029 <1> ; ; bic $60,r2 / su & ex / yes, clear set user id and 20030 <1> ; ; / executable modes 20031 <1> 20032 <1> ; 01/05/2021 20033 <1> ; AX = new mode (9 bits for devices or 12 bits files) 20034 0000426E 8A15[25680000] <1> mov dl, [i.flgs+1] 20035 <1> ; 09/01/2022 20036 00004274 F6C280 <1> test dl, 80h ; regular file 20037 00004277 7416 <1> jz short syschmod1 ; device file 20038 00004279 F6C240 <1> test dl, 40h ; directory 20039 0000427C 7511 <1> jnz short syschmod1 20040 <1> ; regular file 20041 0000427E 6625FF0D <1> and ax, 0DFFh ; clear bit 9, 12-15 (of new mode) 20042 <1> ; clear bit 8,10,11 of current mode/flags 20043 00004282 80E2F2 <1> and dl, 0F2h ; and dl, 11110010b 20044 <1> syschmod0: 20045 00004285 08D4 <1> or ah, dl 20046 00004287 66A3[24680000] <1> mov [i.flgs], ax 20047 0000428D EB45 <1> jmp short syschmod2 20048 <1> syschmod1: 20049 <1> ; device or directory 20050 0000428F 6625B601 <1> and ax, 1B6h ; clear bit 9-15 & bit 0,3,6 (EXEC bits) 20051 <1> ; clear bit 8 (IREAD) of current mode/flags 20052 <1> ; (dl contains flag bits 8-15) 20053 00004293 80E2FE <1> and dl, ~1 ; and dl, 11111110b 20054 00004296 EBED <1> jmp short syschmod0 20055 <1> 20056 <1> ;syschmod1: ; 2: 20057 <1> ;mov [i.flgs], al 20058 <1> ; ; movb r2,i.flgs / move remaining mode to i.flgs 20059 <1> 20060 <1> ; 25/05/2020 - Retro UNIX 386 v2 20061 <1> ;mov byte [imodx], 1 ; (flag means file data is same 20062 <1> ; ; but inode's itself has been modified) 20063 <1> ;call setimod 20064 <1> ;jmp sysret 20065 <1> 20066 <1> ; 25/05/2020 20067 <1> ;jmp short syschmod2 20068 <1> 20069 <1> syschown: ; < change owner of file > 20070 <1> ; 13/03/2022 20071 <1> ; 11/03/2022 20072 <1> ; 14/02/2022 20073 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20074 <1> ; 01/05/2021 20075 <1> ; (change owner and group ID of file) 20076 <1> ; 02/04/2021 20077 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 20078 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 20079 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 20080 <1> ; 20081 <1> ; 'syschown' changes the owner of the file whose name is given 20082 <1> ; as null terminated string pointed to by 'name' has it's owner 20083 <1> ; changed to 'owner' 20084 <1> ; 20085 <1> ; Calling sequence: 20086 <1> ; syschown; name; owner 20087 <1> ; Arguments: 20088 <1> ; name - address of the file name 20089 <1> ; terminated by null byte. 20090 <1> ; owner - (new) owner (number/ID) 20091 <1> ; 20092 <1> ; Inputs: - 20093 <1> ; Outputs: - 20094 <1> ; ............................................................... 20095 <1> ; 20096 <1> ; Retro UNIX 8086 v1 modification: 20097 <1> ; 'syschown' system call has two arguments; so, 20098 <1> ; * 1st argument, name is pointed to by BX register 20099 <1> ; * 2nd argument, owner number is in CX register 20100 <1> ; 20101 <1> ; / name; owner 20102 00004298 E848000000 <1> call isown 20103 <1> ; jsr r0,isown / get the i-node and check user status 20104 <1> 20105 <1> ; 25/05/2020 20106 <1> ; AL = owner number (return form 'isown', ecx -> eax) 20107 <1> ; 02/04/2021 20108 <1> ; AX = owner number 20109 <1> ; 01/05/2021 20110 <1> ; byte 2 of EAX is group number 20111 <1> 20112 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 20113 <1> ; ; tstb u.uid / super user 20114 <1> ;jz short syschown1 20115 <1> ; ; beq 2f / yes, 2f 20116 0000429D 66833D[F66C0000]00 <1> cmp word [u.uid], 0 20117 000042A5 741F <1> jz short syschown1 20118 <1> 20119 <1> ;test byte [i.flgs], 20h ; 32 20120 <1> ; ; bit $40,i.flgs / no, set userid on execution? 20121 <1> ;;jnz error 20122 <1> ; ; bne 3f / yes error, could create Trojan Horses 20123 <1> ;jz short syschown1 20124 <1> ; 01/05/2021 20125 <1> ; check set user id on execution flag 20126 <1> ; (protection against Trojan Horses) 20127 <1> 20128 <1> ; ((Note: UNIX v7 x86 'chown' source code in 'sys4.c' 20129 <1> ; does not contain this protection)) 20130 <1> 20131 <1> ; 14/02/2022 20132 000042A7 8A15[25680000] <1> mov dl, [i.flgs+1] 20133 000042AD F6C280 <1> test dl, 80h ; IFREG ; RUNIX v2 inode flags 20134 000042B0 7405 <1> jz short syschown_err ; device file ! 20135 <1> ; 09/01/2022 20136 <1> ;test byte [i.flgs+1], 08h ; ISUID ; RUNIX v2 inode flags 20137 <1> ; 14/02/2022 20138 000042B2 F6C208 <1> test dl, 08h ; set user id on execution 20139 000042B5 740F <1> jz short syschown1 ; 11/03/2022 20140 <1> ; 11/03/2022 20141 <1> ; bit $40,i.flgs / no, set userid on execution? 20142 <1> ; bne 3f / yes error, could create Trojan Horses 20143 <1> syschown_err: 20144 <1> ; 'permission denied !' 20145 000042B7 C705[186D0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; 11 20146 000042BF 0000 <1> 20147 000042C1 E99FEEFFFF <1> jmp error 20148 <1> syschown1: ; 2: 20149 <1> ;; AL = owner (number/ID) 20150 <1> ;mov [i.uid], al ; 23/06/2015 20151 <1> ; ; movb r2,i.uid / no, put the new owners id 20152 <1> ; ; / in the i-node 20153 <1> ; 02/04/2021 (Retro UNIX 386 v2) 20154 <1> ; AX = owner number 20155 000042C6 66A3[28680000] <1> mov [i.uid], ax ; owner 20156 <1> ; 13/03/2022 20157 <1> ;; 14/02/2022 (Retro UNIX 386 v1.2) 20158 <1> ;test dl, 04h ; ISGID ; set grup id on execution 20159 <1> ;jz short syschown2 20160 <1> ; 01/05/2021 (Retro UNIX 386 v2) 20161 000042CC C1E810 <1> shr eax, 16 20162 000042CF A2[2A680000] <1> mov [i.gid], al ; group 20163 <1> syschown2: 20164 <1> ; 25/05/2020 - Retro UNIX 386 v2 20165 <1> syschmod2: 20166 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20167 000042D4 C605[956C0000]01 <1> mov byte [imodx], 1 ; (flag means file data is same 20168 <1> ; but inode's itself has been modified) 20169 000042DB E8260A0000 <1> call setimod ; 25/05/2020 20170 <1> 20171 000042E0 E9A0EEFFFF <1> jmp sysret 20172 <1> 20173 <1> ; 1: 20174 <1> ; jmp sysret4 20175 <1> ; 3: 20176 <1> ; jmp error 20177 <1> 20178 <1> isown: 20179 <1> ; 11/03/2022 20180 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20181 <1> ; 06/11/2021 20182 <1> ; 12/06/2021 20183 <1> ; 01/05/2021 20184 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 20185 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 20186 <1> ; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1) 20187 <1> ; 20188 <1> ; 'isown' is given a file name (the 1st argument). 20189 <1> ; It find the i-number of that file via 'namei' 20190 <1> ; then gets the i-node into core via 'iget'. 20191 <1> ; It then tests to see if the user is super user. 20192 <1> ; If not, it checks to see if the user is owner of 20193 <1> ; the file. If he is not an error occurs. 20194 <1> ; If user is the owner 'setimod' is called to indicate 20195 <1> ; the inode has been modified and the 2nd argument of 20196 <1> ; the call is put in r2. 20197 <1> ; 20198 <1> ; INPUTS -> 20199 <1> ; arguments of syschmod and syschown calls 20200 <1> ; OUTPUTS -> 20201 <1> ; u.uid - id of user 20202 <1> ; imod - set to a 1 20203 <1> ; r2 - contains second argument of the system call 20204 <1> ; 20205 <1> ; ((AX=R2) output as 2nd argument) 20206 <1> ; 20207 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 20208 <1> ; 20209 <1> ; jsr r0,arg2 / u.namep points to file name 20210 <1> ;; ! 2nd argument on top of stack ! 20211 <1> ;; 22/06/2015 - 32 bit modifications 20212 <1> ;; 07/07/2013 20213 000042E5 891D[C06C0000] <1> mov [u.namep], ebx ;; 1st argument 20214 000042EB 51 <1> push ecx ;* ; 2nd argument 20215 <1> ;; 20216 000042EC E88BFDFFFF <1> call namei 20217 <1> ; jsr r0,namei / get its i-number 20218 <1> ; Retro UNIX 8086 v1 modification ! 20219 <1> ; ax = 0 -> file not found 20220 <1> ;and ax, ax 20221 <1> ;jz error 20222 <1> ;jc error ; 27/05/2013 20223 <1> ; br error3 20224 000042F1 730F <1> jnc short isown1 ; 25/05/2020 (isown0 -> isown1) 20225 <1> ; 'file not found !' error 20226 000042F3 C705[186D0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 20227 000042FB 0000 <1> 20228 000042FD E963EEFFFF <1> jmp error 20229 <1> isown1: 20230 00004302 E86E080000 <1> call iget 20231 <1> ; jsr r0,iget / get i-node into core 20232 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 20233 <1> ;; 06/11/2021 20234 <1> ;jnc short isown3 20235 <1> ;mov [u.error], eax 20236 <1> ;jmp error 20237 <1> ;isown3: 20238 <1> ; check if it is super user ID 20239 <1> ; 09/01/2022 (Retro UNIX 386 v2 fs inode structure) 20240 00004307 66A1[F66C0000] <1> mov ax, [u.uid] 20241 0000430D 6609C0 <1> or ax, ax 20242 <1> ;mov al, [u.uid] ; 02/08/2013 20243 <1> ;or al, al 20244 <1> ; tstb u.uid / super user? 20245 <1> ; 12/06/2021 20246 00004310 7418 <1> jz short isown2 ; 25/05/2020 (isown1 -> isown2) 20247 <1> ; beq 1f / yes, branch 20248 <1> 20249 <1> ; check user ID (if same with file's owner) 20250 00004312 663B05[28680000] <1> cmp ax, [i.uid] ; 09/01/2022 20251 <1> ;cmp al, [i.uid] 20252 <1> ; cmpb i.uid,u.uid / no, is this the owner of 20253 <1> ; / the file 20254 <1> ;jne error 20255 <1> ; beq 1f / yes 20256 <1> ; jmp error3 / no, error 20257 <1> ; 11/03/2022 20258 00004319 740F <1> je short isown2 ; 25/05/2020 20259 <1> ;; 01/05/2021 20260 <1> ;jne short isown_err 20261 <1> 20262 <1> ; 11/03/2022 (*) 20263 <1> ; Note: It is seen as original unix (v5-v7) kernel 20264 <1> ; source handles 'u.gid' for group permissions 20265 <1> ; but kernel uses 'u.uid' as primary and unic 20266 <1> ; (singular) user id/number; a user group 20267 <1> ; does/can not contain same user id/number 20268 <1> ; with anotner group. So, if active/current 20269 <1> ; user ID is same with file's owner id, 20270 <1> ; group id check is not needed. 20271 <1> ; ([u.uid] = [i.uid] is enough to confirm) 20272 <1> 20273 <1> ; 01/05/2021 20274 <1> ;mov ax, [u.uid] 20275 <1> ;or ax, ax 20276 <1> ;jz short isown2 20277 <1> ;cmp ax, [i.uid] 20278 <1> ;;je short isown2 20279 <1> ;jne short isown_err 20280 <1> 20281 <1> ; 01/05/2021 20282 <1> ; ((Note: UNIX v7 x86 'chown', 'chmod' procedures 20283 <1> ; and their sub procedures do not check group ID)) 20284 <1> ; (('sys4.c', 'fio.c')) 20285 <1> 20286 <1> ; 11/03/2022 (*) 20287 <1> ; 01/05/2021 20288 <1> ; check group ID (if same with group of file's owner) 20289 <1> ;mov al, [u.gid] 20290 <1> ;cmp al, [i.gid] 20291 <1> ;je short isown2 20292 <1> isown_err: 20293 0000431B C705[186D0000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER ; 11 20294 00004323 0000 <1> 20295 <1> ; 'permission denied !' error 20296 00004325 E93BEEFFFF <1> jmp error 20297 <1> 20298 <1> ; 25/05/2020 20299 <1> ;isown2: ; 1: 20300 <1> ; call setimod 20301 <1> ; ; jsr r0,setimod / indicates 20302 <1> ; ; ; / i-node has been modified 20303 <1> isown2: 20304 <1> ; 25/05/2020 20305 0000432A 58 <1> pop eax ;* ; 2nd argument 20306 <1> ; mov (sp)+,r2 / mode is put in r2 20307 <1> ; / (u.off put on stack with 2nd arg) 20308 0000432B C3 <1> retn 20309 <1> 20310 <1> ;;arg: ; < get system call arguments > 20311 <1> ; 'arg' extracts an argument for a routine whose call is 20312 <1> ; of form: 20313 <1> ; sys 'routine' ; arg1 20314 <1> ; or 20315 <1> ; sys 'routine' ; arg1 ; arg2 20316 <1> ; or 20317 <1> ; sys 'routine' ; arg1;...;arg10 (sys exec) 20318 <1> ; 20319 <1> ; INPUTS -> 20320 <1> ; u.sp+18 - contains a pointer to one of arg1..argn 20321 <1> ; This pointers's value is actually the value of 20322 <1> ; update pc at the the trap to sysent (unkni) is 20323 <1> ; made to process the sys instruction 20324 <1> ; r0 - contains the return address for the routine 20325 <1> ; that called arg. The data in the word pointer 20326 <1> ; to by the return address is used as address 20327 <1> ; in which the extracted argument is stored 20328 <1> ; 20329 <1> ; OUTPUTS -> 20330 <1> ; 'address' - contains the extracted argument 20331 <1> ; u.sp+18 - is incremented by 2 20332 <1> ; r1 - contains the extracted argument 20333 <1> ; r0 - points to the next instruction to be 20334 <1> ; executed in the calling routine. 20335 <1> ; 20336 <1> 20337 <1> ; mov u.sp,r1 20338 <1> ; mov *18.(r1),*(r0)+ / put argument of system call 20339 <1> ; / into argument of arg2 20340 <1> ; add $2,18.(r1) / point pc on stack 20341 <1> ; / to next system argument 20342 <1> ; rts r0 20343 <1> 20344 <1> ;;arg2: ; < get system calls arguments - with file name pointer> 20345 <1> ; 'arg2' takes first argument in system call 20346 <1> ; (pointer to name of the file) and puts it in location 20347 <1> ; u.namep; takes second argument and puts it in u.off 20348 <1> ; and on top of the stack 20349 <1> ; 20350 <1> ; INPUTS -> 20351 <1> ; u.sp, r0 20352 <1> ; 20353 <1> ; OUTPUTS -> 20354 <1> ; u.namep 20355 <1> ; u.off 20356 <1> ; u.off pushed on stack 20357 <1> ; r1 20358 <1> ; 20359 <1> 20360 <1> ; jsr r0,arg; u.namep / u.namep contains value of 20361 <1> ; / first arg in sys call 20362 <1> ; jsr r0,arg; u.off / u.off contains value of 20363 <1> ; / second arg in sys call 20364 <1> ; mov r0,r1 / r0 points to calling routine 20365 <1> ; mov (sp),r0 / put operation code back in r0 20366 <1> ; mov u.off,(sp) / put pointer to second argument 20367 <1> ; / on stack 20368 <1> ; jmp (r1) / return to calling routine 20369 <1> 20370 <1> systime: ; / get time of year 20371 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 20372 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 20373 <1> ; 20374 <1> ; 20/06/2013 20375 <1> ; 'systime' gets the time of the year. 20376 <1> ; The present time is put on the stack. 20377 <1> ; 20378 <1> ; Calling sequence: 20379 <1> ; systime 20380 <1> ; Arguments: - 20381 <1> ; 20382 <1> ; Inputs: - 20383 <1> ; Outputs: sp+2, sp+4 - present time 20384 <1> ; ............................................................... 20385 <1> ; 20386 <1> ; Retro UNIX 8086 v1 modification: 20387 <1> ; 'systime' system call will return to the user 20388 <1> ; with unix time (epoch) in DX:AX register pair 20389 <1> ; 20390 <1> ; !! Major modification on original Unix v1 'systime' 20391 <1> ; system call for PC compatibility !! 20392 <1> 20393 0000432C E809E9FFFF <1> call epoch 20394 00004331 A3[A46C0000] <1> mov [u.r0], eax 20395 <1> ; mov s.time,4(sp) 20396 <1> ; mov s.time+2,2(sp) / put the present time 20397 <1> ; / on the stack 20398 <1> ; br sysret4 20399 00004336 E94AEEFFFF <1> jmp sysret 20400 <1> 20401 <1> sysstime: ; / set time 20402 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20403 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 20404 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 20405 <1> ; 20406 <1> ; 'sysstime' sets the time. Only super user can use this call. 20407 <1> ; 20408 <1> ; Calling sequence: 20409 <1> ; sysstime 20410 <1> ; Arguments: - 20411 <1> ; 20412 <1> ; Inputs: sp+2, sp+4 - time system is to be set to. 20413 <1> ; Outputs: - 20414 <1> ; ............................................................... 20415 <1> ; 20416 <1> ; Retro UNIX 8086 v1 modification: 20417 <1> ; the user calls 'sysstime' with unix (epoch) time 20418 <1> ; (to be set) is in CX:BX register pair as two arguments. 20419 <1> ; 20420 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 20421 <1> ; to get sysstime system call arguments from the user; 20422 <1> ; * 1st argument, lowword of unix time is in BX register 20423 <1> ; * 2nd argument, highword of unix time is in CX register 20424 <1> ; 20425 <1> ; !! Major modification on original Unix v1 'sysstime' 20426 <1> ; system call for PC compatibility !! 20427 <1> 20428 <1> ; 09/01/2022 (Retro UNIX 386 v2 fs inode structure) 20429 0000433B 66833D[F66C0000]00 <1> cmp word [u.uid], 0 ; 16 bit user ID 20430 <1> ;cmp byte [u.uid], 0 20431 <1> ; tstb u.uid / is user the super user 20432 <1> ;ja error 20433 <1> ; bne error4 / no, error 20434 00004343 760F <1> jna short systime1 20435 <1> ; 'permission denied !' 20436 00004345 C705[186D0000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 20437 0000434D 0000 <1> 20438 0000434F E911EEFFFF <1> jmp error 20439 <1> systime1: 20440 <1> ; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version) 20441 <1> ; EBX = unix (epoch) time (from user) 20442 00004354 89D8 <1> mov eax, ebx 20443 00004356 E85CEAFFFF <1> call set_date_time 20444 <1> ; mov 4(sp),s.time 20445 <1> ; mov 2(sp),s.time+2 / set the system time 20446 0000435B E925EEFFFF <1> jmp sysret 20447 <1> ; br sysret4 20448 <1> 20449 <1> sysbreak: 20450 <1> ; 18/10/2015 20451 <1> ; 07/10/2015 20452 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 20453 <1> ; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1) 20454 <1> ; 20455 <1> ; 'sysbreak' sets the programs break points. 20456 <1> ; It checks the current break point (u.break) to see if it is 20457 <1> ; between "core" and the stack (sp). If it is, it is made an 20458 <1> ; even address (if it was odd) and the area between u.break 20459 <1> ; and the stack is cleared. The new breakpoint is then put 20460 <1> ; in u.break and control is passed to 'sysret'. 20461 <1> ; 20462 <1> ; Calling sequence: 20463 <1> ; sysbreak; addr 20464 <1> ; Arguments: - 20465 <1> ; 20466 <1> ; Inputs: u.break - current breakpoint 20467 <1> ; Outputs: u.break - new breakpoint 20468 <1> ; area between old u.break and the stack (sp) is cleared. 20469 <1> ; ............................................................... 20470 <1> ; 20471 <1> ; Retro UNIX 8086 v1 modification: 20472 <1> ; The user/application program puts breakpoint address 20473 <1> ; in BX register as 'sysbreak' system call argument. 20474 <1> ; (argument transfer method 1) 20475 <1> ; 20476 <1> ; NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 ! 20477 <1> ; ((!'sysbreak' is not needed in Retro UNIX 8086 v1!)) 20478 <1> ; NOTE: 20479 <1> ; 'sysbreak' clears extended part (beyond of previous 20480 <1> ; 'u.break' address) of user's memory for original unix's 20481 <1> ; 'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013) 20482 <1> 20483 <1> ; mov u.break,r1 / move users break point to r1 20484 <1> ; cmp r1,$core / is it the same or lower than core? 20485 <1> ; blos 1f / yes, 1f 20486 <1> ; 23/06/2015 20487 00004360 8B2D[D46C0000] <1> mov ebp, [u.break] ; virtual address (offset) 20488 <1> ;and ebp, ebp 20489 <1> ;jz short sysbreak_3 20490 <1> ; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!! 20491 <1> ; (Even break point address is not needed for Retro UNIX 386 v1) 20492 00004366 8B15[9C6C0000] <1> mov edx, [u.sp] ; kernel stack at the beginning of sys call 20493 0000436C 83C20C <1> add edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 20494 <1> ; 07/10/2015 20495 0000436F 891D[D46C0000] <1> mov [u.break], ebx ; virtual address !!! 20496 <1> ; 20497 00004375 3B1A <1> cmp ebx, [edx] ; compare new break point with 20498 <1> ; with top of user's stack (virtual!) 20499 00004377 7327 <1> jnb short sysbreak_3 20500 <1> ; cmp r1,sp / is it the same or higher 20501 <1> ; / than the stack? 20502 <1> ; bhis 1f / yes, 1f 20503 00004379 89DE <1> mov esi, ebx 20504 0000437B 29EE <1> sub esi, ebp ; new break point - old break point 20505 0000437D 7621 <1> jna short sysbreak_3 20506 <1> ;push ebx 20507 <1> sysbreak_1: 20508 0000437F 89EB <1> mov ebx, ebp 20509 00004381 E841E4FFFF <1> call get_physical_addr ; get physical address 20510 00004386 0F826DFEFFFF <1> jc tr_addr_nm_err 20511 <1> ; 18/10/2015 20512 0000438C 89C7 <1> mov edi, eax 20513 0000438E 29C0 <1> sub eax, eax ; 0 20514 <1> ; ECX = remain byte count in page (1-4096) 20515 00004390 39CE <1> cmp esi, ecx 20516 00004392 7302 <1> jnb short sysbreak_2 20517 00004394 89F1 <1> mov ecx, esi 20518 <1> sysbreak_2: 20519 00004396 29CE <1> sub esi, ecx 20520 00004398 01CD <1> add ebp, ecx 20521 0000439A F3AA <1> rep stosb 20522 0000439C 09F6 <1> or esi, esi 20523 0000439E 75DF <1> jnz short sysbreak_1 20524 <1> ; 20525 <1> ; bit $1,r1 / is it an odd address 20526 <1> ; beq 2f / no, its even 20527 <1> ; clrb (r1)+ / yes, make it even 20528 <1> ; 2: / clear area between the break point and the stack 20529 <1> ; cmp r1,sp / is it higher or same than the stack 20530 <1> ; bhis 1f / yes, quit 20531 <1> ; clr (r1)+ / clear word 20532 <1> ; br 2b / go back 20533 <1> ;pop ebx 20534 <1> sysbreak_3: ; 1: 20535 <1> ;mov [u.break], ebx ; virtual address !!! 20536 <1> ; jsr r0,arg; u.break / put the "address" 20537 <1> ; / in u.break (set new break point) 20538 <1> ; br sysret4 / br sysret 20539 000043A0 E9E0EDFFFF <1> jmp sysret 20540 <1> 20541 <1> maknod: 20542 <1> ; 18/07/2022 20543 <1> ; 12/03/2022 20544 <1> ; 11/03/2022 20545 <1> ; 14/02/2022 20546 <1> ; 10/01/2022 20547 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20548 <1> ; 06/11/2021 (Retro UNIX 386 v2) 20549 <1> ; 15/08/2021 20550 <1> ; 06/05/2021 20551 <1> ; 02/05/2021 20552 <1> ; 01/04/2021 20553 <1> ; 27/03/2021 20554 <1> ; 25/03/2021 (Retro UNIX 386 v2 - Beginning) 20555 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 20556 <1> ; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 20557 <1> ; 20558 <1> ; 'maknod' creates an i-node and makes a directory entry 20559 <1> ; for this i-node in the current directory. 20560 <1> ; 20561 <1> ; INPUTS -> 20562 <1> ; r1 - contains mode 20563 <1> ; ii - current directory's i-number 20564 <1> ; 20565 <1> ; OUTPUTS -> 20566 <1> ; u.dirbuf - contains i-number of free i-node 20567 <1> ; i.flgs - flags in new i-node 20568 <1> ; i.uid - filled with u.uid 20569 <1> ; i.nlks - 1 is put in the number of links 20570 <1> ; i.ctim - creation time 20571 <1> ; i.ctim+2 - modification time 20572 <1> ; imod - set via call to setimod 20573 <1> ; 20574 <1> ; ((AX = R1)) input 20575 <1> ; 20576 <1> ; (Retro UNIX Prototype : 20577 <1> ; 30/10/2012 - 01/03/2013, UNIXCOPY.ASM) 20578 <1> ; ((Modified registers: eax, edx, ebx, ecx, esi, edi, ebp)) 20579 <1> 20580 <1> ; 27/03/2021 20581 <1> ; INPUT: 20582 <1> ; AX = mode 20583 <1> ; 20584 <1> ; ('maknod' is called by 'syscreat' and 'sysmkdir') 20585 <1> ; (('syscreat' and 'sysmkdir' will set AX input)) 20586 <1> 20587 <1> ; 27/03/2021 20588 <1> ; Retro UNIX 386 v2 inode mode flags (ref: 'ux.s') 20589 <1> ; for File Inode: (high byte) 20590 <1> ; IFREG - 1 = regular file (8000h) 20591 <1> ; IFDIR - 1 = directory (4000h) 20592 <1> ; IRSVD - 0 = reserved bit (2000h) ; Mounted flag for dirs 20593 <1> ; ILARG - large file addressing bit (1000h) 20594 <1> ; ISUID - set user id on exec (800h) 20595 <1> ; ISGID - set group id on exec (400h) 20596 <1> ; IEXTT - 1 = use extents (200h) 20597 <1> ; IREAD - read, owner (100h) 20598 <1> ; for Device Inode: (high byte) 20599 <1> ; IFREG - 0 = device file (8000h) 20600 <1> ; IFBLK - 1 = block device (4000h) 20601 <1> ; IFCHR - character special (2000h) -always 1- 20602 <1> ; IFIFO - fifo special (1000h) 20603 <1> ; IPIPE - pipe special (800h) ; 07/02/2020 20604 <1> ; IREDIR - redirected (400h) ; 07/02/2020 20605 <1> ; IEXTR - 1 = external device driver (200h) 20606 <1> ; IREAD - read, owner (100h) 20607 <1> 20608 <1> ;; / r1 contains the mode 20609 <1> ;or ah, 80h ; 10000000b 20610 <1> ; ; bis $100000,r1 / allocate flag set 20611 <1> 20612 <1> ; 14/02/2022 20613 <1> ; input -> 20614 <1> ; [u.namep] points to the file name address 20615 <1> ; (in the user's memory space) 20616 <1> ; [u.dirp] points to empty slot in the directory 20617 <1> 20618 <1> ; high 3 bit will be checked here 20619 <1> ; (ref: unix v7 x86 source, iget.c) 20620 <1> 20621 <1> ; ; 27/03/2021 20622 <1> ; test ah, 0E0h ; 80h+40h+20h 20623 <1> ; jnz short maknod0 20624 <1> ; 20625 <1> ; ; ('syscreat' clears ILARG & IEXTT bits) 20626 <1> ; ;and ah, ~0Ch ; clear ILARG & IEXTT bits 20627 <1> ; ; ; user can set ISUID & ISGID bits 20628 <1> ; 20629 <1> ; or ah, 80h ; IFREG 20630 <1> ;maknod0: 20631 000043A5 50 <1> push eax ; ***** ; 27/03/2021 (32 bit push, pop) 20632 <1> ; mov r1,-(sp) / put mode on stack 20633 <1> ; 31/07/2013 20634 <1> ;mov ax, [ii] ; move current i-number to AX/r1 20635 <1> ; ; mov ii,r1 / move current i-number to r1 20636 <1> ;mov dl, 1 ; owner flag mask 20637 <1> ; 15/08/2021 20638 <1> ;movzx eax, word [ii] ; move current i-number to EAX 20639 <1> ; 09/01/2022 20640 000043A6 A1[7C6C0000] <1> mov eax, [ii] ; move current i-number to EAX 20641 <1> ; 25/03/2021 20642 000043AB 66BA8000 <1> mov dx, 80h ; IWRITE - write,owner 20643 000043AF E8AB080000 <1> call access 20644 <1> ; jsr r0,access; 1 / get its i-node into core 20645 <1> ; 15/08/2021 20646 <1> ; NOTE: cpu will not return here if there is a permission error 20647 <1> ; (it will jump to 'error' address from/in 'access') 20648 <1> 20649 000043B4 50 <1> push eax ; **** (parent) ; 27/03/2021 (32 bit push, pop) 20650 <1> ; mov r1,-(sp) / put i-number on stack 20651 <1> ;mov ax, 40 20652 <1> ; ; mov $40.,r1 / r1 = 40 20653 <1> ; 27/03/2021 20654 000043B5 31C0 <1> xor eax, eax 20655 <1> ;;dec ax ; 0FFFFh 20656 <1> ; 15/08/2021 20657 <1> ;dec eax ; 0FFFFFFFFh 20658 <1> ; 01/04/2021 20659 <1> ;maknod1: ; 1: / scan for a free i-node (next 4 instructions) 20660 <1> ;;inc ax 20661 <1> ; ; inc r1 / r1 = r1 + 1 20662 <1> ; 15/08/2021 20663 <1> ;inc eax 20664 <1> ; 27/03/2021 - Retro UNIX 386 v2 20665 <1> ; eax = 0 -> start from first free inode 20666 <1> ; eax > 0 -> locate this inode on the inode map buffer 20667 <1> ; NOTE: 20668 <1> ; Retro UNIX 386 v2 'imap' is mostly different than v1 'imap' 20669 <1> ; ('imap' will not check inode table) 20670 000043B7 E8980A0000 <1> call imap 20671 <1> ; jsr r0,imap / get byte address and bit position in 20672 <1> ; / inode map in r2 & m 20673 <1> ; 09/01/2022 20674 <1> ; (cpu will not return here if there would be an eror in imap) 20675 <1> ; 15/08/2021 20676 <1> ;jc short maknod_err 20677 <1> 20678 <1> ; DX (MQ) has a 1 in the calculated bit position 20679 <1> ; eBX (R2) has byte address of the byte with allocation bit 20680 <1> 20681 <1> ; 06/11/2021 20682 <1> ; ebp = superblock buffer address 20683 <1> ; eax = inode number 20684 <1> ; 10/01/2022 20685 <1> ; [ebp+SB.ImapBuffer] = physical block/sector number 20686 <1> ; of current IMAP sector 20687 <1> 20688 <1> ; 27/03/2021 20689 <1> ; If cpu is here, there is not an error 20690 <1> ; and EBX points to inode map buffer 20691 <1> ; DL has 1 at bit position which is for free inode 20692 <1> ; (E)AX = inode number 20693 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 20694 <1> ; ECX = byte offset from the (start of) inode map buffer 20695 <1> 20696 <1> ; 15/08/2021 20697 <1> maknod1: 20698 <1> ; 22/06/2015 - NOTE for next Retro UNIX version: 20699 <1> ; Inode count must be checked here 20700 <1> ; (Original UNIX v1 did not check inode count here !?) 20701 000043BC 8413 <1> test [ebx], dl 20702 <1> ; bitb mq,(r2) / is the i-node active 20703 <1> ;jnz short maknod1 20704 <1> ; ; bne 1b / yes, try the next one 20705 <1> ; 15/08/2021 20706 000043BE 7408 <1> jz short maknod3 ; free inode (inactive inode) 20707 <1> maknod2: 20708 000043C0 40 <1> inc eax 20709 000043C1 E8B20A0000 <1> call imap_x ; next call to imap (bypass 1st call code) 20710 <1> ; 10/01/2022 20711 <1> ; (cpu will/would not return here 20712 <1> ; if there is/was an error in 'imap_x') 20713 <1> ;jnc short maknod1 20714 000043C6 EBF4 <1> jmp short maknod1 20715 <1> 20716 <1> ; 14/02/2022 20717 <1> ;maknod_err: 20718 <1> ; ; 15/08/2021 20719 <1> ; ;pop edx ; two pops for stack alignment 20720 <1> ; ;pop edx ; (may not be needed while jumping to 'error') 20721 <1> ; mov [u.error], eax 20722 <1> ; jmp error 20723 <1> maknod3: 20724 <1> ; 10/01/2022 20725 <1> ; ebp = superblock buffer address 20726 <1> ; eax = (free) inode number 20727 <1> ; [ebp+SB.ImapBuffer] = physical block/sector number 20728 <1> ; of current IMAP sector 20729 <1> ; EBX = buffer address/offset for relevant alloc byte 20730 <1> ; DL has 1 at bit position which is for free inode 20731 <1> ; 20732 <1> ; ECX = byte offset from the (start of) inode map buffer 20733 <1> 20734 <1> ;mov [ebp+SB.LastInode], eax ; (free) inode number 20735 <1> 20736 000043C8 50 <1> push eax ; *** 20737 000043C9 51 <1> push ecx ; ** 20738 000043CA 52 <1> push edx ; * 20739 <1> ; 18/07/2022 20740 <1> ;push ebp ; @ ; 11/03/2022 20741 <1> 20742 000043CB 8B457C <1> mov eax, [ebp+SB.ImapBuffer] 20743 <1> 20744 000043CE E821160000 <1> call wslot 20745 <1> ; ebx = buffer data address (write operation bit is set) 20746 <1> ; eax = physical sector number 20747 <1> ; Note: ebx contains addr of the 1st buffer in the buf chain 20748 <1> ; (the last allocated buffer becomes the 1st in buffer chain) 20749 <1> 20750 <1> ; 18/07/2022 20751 <1> ;pop ebp ; @ ; 11/03/2022 20752 <1> 20753 <1> ;mov [ebp+SB.ImapBuffer], ebx 20754 <1> ; save inode map buffer address 20755 000043D3 5A <1> pop edx ; * 20756 000043D4 59 <1> pop ecx ; ** 20757 000043D5 01CB <1> add ebx, ecx ; + byte offset (for allocation bit pos) 20758 <1> 20759 <1> ; set allocation bit (for this new inode) ; 10/01/2022 20760 000043D7 0813 <1> or [ebx], dl 20761 <1> ; bisb mq,(r2) / no, make it active 20762 <1> ; / (put a 1 in the bit map) 20763 <1> ;push ebp ; @ 20764 000043D9 E823160000 <1> call dskwr ; writes the 1st buffer to sector 20765 <1> ; (at the beginning/head of the buffer chain) 20766 <1> ;pop ebp ; @ 20767 <1> 20768 <1> ; if we are here, buffer has been written to disk successfully 20769 <1> ; (otherwise cpu would jump to 'error' address) 20770 <1> 20771 <1> ; set superblock modified flag 20772 000043DE BA[966C0000] <1> mov edx, smod 20773 000043E3 F605[816C0000]01 <1> test byte [cdev], 1 ; mounted device ? 20774 000043EA 7401 <1> jz short maknod4 ; no, root device 20775 <1> ; yes, mounted device 20776 <1> ;mov edx, mmod 20777 000043EC 42 <1> inc edx ; edx = offset mmod 20778 <1> maknod4: 20779 000043ED FE02 <1> inc byte [edx] ; superblock modified ! 20780 <1> 20781 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20782 <1> ;; 20783 <1> ;; 27/03/2021 20784 <1> ;; (ref: 'UNIXHDCP.ASM', 'mak_nod', 18/01/2020) 20785 <1> ;or byte [smod], 2 ; inode map modified 20786 <1> ;; 01/04/2021 20787 <1> ;;or byte [imapbuf_hdr+bufhdr.status], 2 20788 <1> ;or byte [imapbuf_hdr], 2 ; set modified flag bit 20789 <1> ; 02/05/2021 20790 <1> ;or byte [esi+ldrv.b_status], 2 ; inode map modified 20791 <1> ; 15/08/2021 20792 <1> ; 06/05/2021 20793 <1> ;or byte [esi+ldrv.status], 2 ; inode map modified 20794 <1> ;;or byte [sysbuf_hdr], 2 ; set modified flag bit 20795 <1> 20796 <1> ;mov eax, [ebp+SB.LastInode] ; (free) inode number 20797 <1> ;push eax ; *** 20798 <1> 20799 <1> ; 12/03/2022 20800 <1> ; increase first free inode number 20801 000043EF 8B0424 <1> mov eax, [esp] ; *** 20802 000043F2 40 <1> inc eax ; next inode number 20803 <1> ; (free inode search start value) 20804 000043F3 894534 <1> mov [ebp+SB.FirstFreeIno], eax 20805 <1> 20806 <1> ; 12/03/2022 20807 <1> ; decrease free inode count 20808 000043F6 8B5530 <1> mov edx, [ebp+SB.FreeInodes] 20809 <1> ;cmp edx, 0FFFFFFFFh 20810 <1> ;je short maknod5 ; invalid 20811 000043F9 42 <1> inc edx ; 0FFFFFFFFh -> 0 20812 000043FA 7405 <1> jz short maknod5 ; invalid 20813 000043FC 4A <1> dec edx 20814 000043FD 4A <1> dec edx 20815 000043FE 895530 <1> mov [ebp+SB.FreeInodes], edx ; -1 20816 <1> maknod5: 20817 00004401 E851170000 <1> call get_system_time 20818 <1> ; eax = current time (as unix epoch time) 20819 00004406 89455C <1> mov [ebp+SB.ModifTime], eax 20820 <1> 20821 00004409 58 <1> pop eax ; *** ; inode number 20822 <1> ;; 20823 0000440A E866070000 <1> call iget 20824 <1> ; jsr r0,iget / get i-node into core 20825 <1> ; 09/01/2022 20826 <1> ; (If cpu is here, there was/is not an error!) 20827 <1> ; 06/11/2021 20828 <1> ;jc short maknod_err 20829 <1> 20830 <1> ;test word [i.flgs], 8000h 20831 <1> ; ; tst i.flgs / is i-node already allocated 20832 <1> ;jnz short maknod1 20833 <1> ; ; blt 1b / yes, look for another one 20834 <1> ; 27/03/2021 20835 <1> ; (Retro UNIX 386 v2 inode flags) 20836 0000440F F605[25680000]E0 <1> test byte [i.flgs+1], 0E0h ; 80h+40h+20h 20837 <1> ;jnz short maknod1 ; i-node already allocated 20838 <1> ; ; (as it is in inode table) 20839 <1> ; 15/08/2021 20840 00004416 75A8 <1> jnz short maknod2 ; defective inode map !? 20841 <1> 20842 <1> ; AX = free inode number 20843 00004418 66A3[DC6C0000] <1> mov [u.dirbuf], ax 20844 <1> ; mov r1,u.dirbuf / no, put i-number in u.dirbuf 20845 0000441E 58 <1> pop eax ; **** (parent) ; 27/03/2021 (32 bit push, pop) 20846 <1> ; mov (sp)+,r1 / get current i-number back 20847 0000441F E851070000 <1> call iget 20848 <1> ; jsr r0,iget / get i-node in core 20849 <1> ; 09/01/2022 20850 <1> ; 06/11/2021 20851 <1> ;jc short maknod_err 20852 <1> 20853 <1> ; 14/02/2022 20854 <1> ; here.. 20855 <1> ; [u.namep] points to the file name address 20856 <1> ; (in the user's memory space) 20857 <1> ; [u.dirp] points to empty slot in the directory 20858 <1> 20859 00004424 E81CF7FFFF <1> call mkdir 20860 <1> ; jsr r0,mkdir / make a directory entry 20861 <1> ; / in current directory 20862 <1> ; 09/01/2022 20863 <1> ; (If cpu is here, there was/is not an error in 'mkdir'!) 20864 <1> ; 06/11/2021 20865 <1> ;jc short maknod_err 20866 <1> 20867 <1> ; (eax = 0) 20868 <1> ;movzx eax, [u.difbuf] ; 06/11/2021 20869 00004429 66A1[DC6C0000] <1> mov ax, [u.dirbuf] 20870 <1> ; mov u.dirbuf,r1 / r1 = new inode number 20871 0000442F E841070000 <1> call iget 20872 <1> ; jsr r0,iget / get it into core 20873 <1> ; jsr r0,copyz; inode; inode+32. / 0 it out 20874 <1> ; 09/01/2022 20875 <1> ; 06/11/2021 20876 <1> ;jc short maknod_err 20877 <1> 20878 <1> ;mov ecx, 8 20879 <1> ; 27/03/2021 20880 00004434 31C9 <1> xor ecx, ecx 20881 00004436 B110 <1> mov cl, 16 ; 64 bit inodes 20882 00004438 31C0 <1> xor eax, eax ; 0 20883 0000443A BF[24680000] <1> mov edi, inode 20884 0000443F F3AB <1> rep stosd 20885 <1> ; 20886 <1> ;pop word [i.flgs] 20887 <1> ; ; mov (sp)+,i.flgs / fill flags 20888 <1> ; 27/03/2021 (32 bit push, pop) 20889 00004441 58 <1> pop eax ; ***** 20890 00004442 66A3[24680000] <1> mov [i.flgs], ax 20891 <1> 20892 <1> ;mov cl, [u.uid] ; 02/08/2013 20893 <1> ;mov [i.uid], cl 20894 <1> ; ; movb u.uid,i.uid / user id 20895 <1> ; 15/08/2021 20896 <1> ; 27/03/2021 20897 00004448 8A0D[FA6C0000] <1> mov cl, [u.gid] ; 8 bit group ID ; 15/08/2021 20898 0000444E 880D[2A680000] <1> mov [i.gid], cl 20899 00004454 668B0D[F66C0000] <1> mov cx, [u.uid] ; 16 bit user ID 20900 0000445B 66890D[28680000] <1> mov [i.uid], cx 20901 <1> 20902 00004462 C605[26680000]01 <1> mov byte [i.nlks], 1 20903 <1> ; movb $1,i.nlks / 1 link 20904 <1> ;call epoch ; Retro UNIX 8086 v1 modification ! 20905 <1> ;mov eax, [s.time] 20906 <1> ;mov [i.ctim], eax 20907 <1> ; mov s.time,i.ctim / time created 20908 <1> ; mov s.time+2,i.ctim+2 / time modified 20909 <1> ; Retro UNIX 8086 v1 modification ! 20910 <1> ; i.ctime=0, i.ctime+2=0 and 20911 <1> ; 'setimod' will set ctime of file via 'epoch' 20912 <1> ;call setimod 20913 <1> ; ; jsr r0,setimod / set modified flag 20914 <1> ;retn 20915 <1> ; ; rts r0 / return 20916 <1> ; 27/03/2021 20917 00004469 E998080000 <1> jmp setimod 20918 <1> 20919 <1> sysseek: ; / moves read write pointer in an fsp entry 20920 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 20921 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 20922 <1> ; 20923 <1> ; 'sysseek' changes the r/w pointer of (3rd word of in an 20924 <1> ; fsp entry) of an open file whose file descriptor is in u.r0. 20925 <1> ; The file descriptor refers to a file open for reading or 20926 <1> ; writing. The read (or write) pointer is set as follows: 20927 <1> ; * if 'ptrname' is 0, the pointer is set to offset. 20928 <1> ; * if 'ptrname' is 1, the pointer is set to its 20929 <1> ; current location plus offset. 20930 <1> ; * if 'ptrname' is 2, the pointer is set to the 20931 <1> ; size of file plus offset. 20932 <1> ; The error bit (e-bit) is set for an undefined descriptor. 20933 <1> ; 20934 <1> ; Calling sequence: 20935 <1> ; sysseek; offset; ptrname 20936 <1> ; Arguments: 20937 <1> ; offset - number of bytes desired to move 20938 <1> ; the r/w pointer 20939 <1> ; ptrname - a switch indicated above 20940 <1> ; 20941 <1> ; Inputs: r0 - file descriptor 20942 <1> ; Outputs: - 20943 <1> ; ............................................................... 20944 <1> ; 20945 <1> ; Retro UNIX 8086 v1 modification: 20946 <1> ; 'sysseek' system call has three arguments; so, 20947 <1> ; * 1st argument, file descriptor is in BX (BL) register 20948 <1> ; * 2nd argument, offset is in CX register 20949 <1> ; * 3rd argument, ptrname/switch is in DX (DL) register 20950 <1> ; 20951 <1> 20952 0000446E E820000000 <1> call seektell 20953 <1> ; AX = u.count 20954 <1> ; BX = *u.fofp 20955 <1> ; jsr r0,seektell / get proper value in u.count 20956 <1> ; add u.base,u.count / add u.base to it 20957 00004473 0305[C86C0000] <1> add eax, [u.base] ; add offset (u.base) to base 20958 00004479 8903 <1> mov [ebx], eax 20959 <1> ; mov u.count,*u.fofp / put result into r/w pointer 20960 0000447B E905EDFFFF <1> jmp sysret 20961 <1> ; br sysret4 20962 <1> 20963 <1> systell: ; / get the r/w pointer 20964 <1> ; 01/03/2022 20965 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20966 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 20967 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 20968 <1> ; 20969 <1> ; Retro UNIX 8086 v1 modification: 20970 <1> ; ! 'systell' does not work in original UNIX v1, 20971 <1> ; it returns with error ! 20972 <1> ; Inputs: r0 - file descriptor 20973 <1> ; Outputs: r0 - file r/w pointer 20974 <1> 20975 <1> ;xor ecx, ecx ; 0 20976 <1> ;mov edx, 1 ; 05/08/2013 20977 <1> ; 09/01/2022 20978 00004480 29D2 <1> sub edx, edx 20979 00004482 FEC2 <1> inc dl 20980 <1> ; edx = 1 20981 <1> ;call seektell 20982 00004484 E810000000 <1> call seektell0 ; 05/08/2013 20983 <1> ;mov ebx, [u.fofp] 20984 <1> ; 01/03/2022 20985 <1> ;mov eax, [ebx] 20986 00004489 A3[A46C0000] <1> mov [u.r0], eax 20987 0000448E E9F2ECFFFF <1> jmp sysret 20988 <1> 20989 <1> ; Original unix v1 'systell' system call: 20990 <1> ; jsr r0,seektell 20991 <1> ; br error4 20992 <1> 20993 <1> seektell: 20994 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 20995 <1> ; 06/11/2021 20996 <1> ; 12/06/2021 20997 <1> ; 06/05/2021 (Retro UNIX 386 v2) 20998 <1> ; 03/01/2016 20999 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 21000 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 21001 <1> ; 21002 <1> ; 'seektell' puts the arguments from sysseek and systell 21003 <1> ; call in u.base and u.count. It then gets the i-number of 21004 <1> ; the file from the file descriptor in u.r0 and by calling 21005 <1> ; getf. The i-node is brought into core and then u.count 21006 <1> ; is checked to see it is a 0, 1, or 2. 21007 <1> ; If it is 0 - u.count stays the same 21008 <1> ; 1 - u.count = offset (u.fofp) 21009 <1> ; 2 - u.count = i.size (size of file) 21010 <1> ; 21011 <1> ; !! Retro UNIX 8086 v1 modification: 21012 <1> ; Argument 1, file descriptor is in BX; 21013 <1> ; Argument 2, offset is in CX; 21014 <1> ; Argument 3, ptrname/switch is in DX register. 21015 <1> ; 21016 <1> ; mov ax, 3 ; Argument transfer method 3 (three arguments) 21017 <1> ; call arg 21018 <1> ; 21019 <1> ; ((Return -> ax = base for offset (position= base+offset)) 21020 <1> ; 21021 00004493 890D[C86C0000] <1> mov [u.base], ecx ; offset 21022 <1> ; jsr r0,arg; u.base / puts offset in u.base 21023 <1> ; 09/01/2022 21024 <1> ; ebx = file descriptor (0 to 9) 21025 <1> seektell0: 21026 00004499 8915[CC6C0000] <1> mov [u.count], edx 21027 <1> ; jsr r0,arg; u.count / put ptr name in u.count 21028 <1> ;mov ax, bx 21029 <1> ; mov *u.r0,r1 / file descriptor in r1 21030 <1> ; / (index in u.fp list) 21031 <1> ; 12/06/2021 21032 <1> ; BX = file descriptor (file number) 21033 0000449F E8A2FBFFFF <1> call getf 21034 <1> ; jsr r0,getf / u.fofp points to 3rd word in fsp entry 21035 <1> ; 09/01/2022 21036 000044A4 09C0 <1> or eax, eax 21037 <1> ;or ax, ax ; i-number of the file 21038 <1> ; mov r1,-(sp) / r1 has i-number of file, 21039 <1> ; / put it on the stack 21040 <1> ;jz error 21041 <1> ; beq error4 / if i-number is 0, not active so error 21042 000044A6 750F <1> jnz short seektell1 21043 000044A8 C705[186D0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 21044 000044B0 0000 <1> 21045 000044B2 E9AEECFFFF <1> jmp error 21046 <1> seektell1: 21047 <1> ; 06/05/2021 21048 <1> ;push eax 21049 <1> ;cmp ah, 80h 21050 <1> ;jb short seektell2 21051 <1> ; ; bgt .+4 / if its positive jump 21052 <1> ;neg ax 21053 <1> ; ; neg r1 / if not make it positive 21054 <1> seektell2: 21055 000044B7 E8B9060000 <1> call iget 21056 <1> ; jsr r0,iget / get its i-node into core 21057 <1> ; 09/01/2022 21058 <1> ; (if there is/was an error in 'iget', cpu will not come here) 21059 <1> ;; 06/11/2021 21060 <1> ;jnc short seektell6 21061 <1> ;mov [u.error], eax 21062 <1> ;jmp error 21063 <1> seektell6: 21064 000044BC 8B1D[B86C0000] <1> mov ebx, [u.fofp] ; 05/08/2013 21065 000044C2 803D[CC6C0000]01 <1> cmp byte [u.count], 1 21066 <1> ; cmp u.count,$1 / is ptr name =1 21067 000044C9 7705 <1> ja short seektell3 21068 <1> ; blt 2f / no its zero 21069 000044CB 7409 <1> je short seektell4 21070 <1> ; beq 1f / yes its 1 21071 000044CD 31C0 <1> xor eax, eax 21072 <1> ;jmp short seektell5 21073 000044CF C3 <1> retn 21074 <1> seektell3: 21075 <1> ; 03/01/2016 21076 <1> ;;movzx eax, word [i.size] 21077 <1> ;mov ax, [i.size] 21078 <1> ; ; mov i.size,u.count / put number of bytes 21079 <1> ; ; / in file in u.count 21080 <1> ;;jmp short seektell5 21081 <1> ; ; br 2f 21082 <1> ; 06/05/2021 - Retro UNIX 386 v2 21083 000044D0 A1[2C680000] <1> mov eax, [i.size] 21084 000044D5 C3 <1> retn 21085 <1> seektell4: ; 1: / ptrname =1 21086 <1> ;mov ebx, [u.fofp] 21087 000044D6 8B03 <1> mov eax, [ebx] 21088 <1> ; mov *u.fofp,u.count / put offset in u.count 21089 <1> ;seektell5: ; 2: / ptrname =0 21090 <1> ;mov [u.count], eax 21091 <1> ;pop eax 21092 <1> ; mov (sp)+,r1 / i-number on stack r1 21093 000044D8 C3 <1> retn 21094 <1> ; rts r0 21095 <1> 21096 <1> sysintr: ; / set interrupt handling 21097 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 21098 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 21099 <1> ; 21100 <1> ; 'sysintr' sets the interrupt handling value. It puts 21101 <1> ; argument of its call in u.intr then branches into 'sysquit' 21102 <1> ; routine. u.tty is checked if to see if a control tty exists. 21103 <1> ; If one does the interrupt character in the tty buffer is 21104 <1> ; cleared and 'sysret'is called. If one does not exits 21105 <1> ; 'sysret' is just called. 21106 <1> ; 21107 <1> ; Calling sequence: 21108 <1> ; sysintr; arg 21109 <1> ; Argument: 21110 <1> ; arg - if 0, interrupts (ASCII DELETE) are ignored. 21111 <1> ; - if 1, intterupts cause their normal result 21112 <1> ; i.e force an exit. 21113 <1> ; - if arg is a location within the program, 21114 <1> ; control is passed to that location when 21115 <1> ; an interrupt occurs. 21116 <1> ; Inputs: - 21117 <1> ; Outputs: - 21118 <1> ; ............................................................... 21119 <1> ; 21120 <1> ; Retro UNIX 8086 v1 modification: 21121 <1> ; 'sysintr' system call sets u.intr to value of BX 21122 <1> ; then branches into sysquit. 21123 <1> ; 21124 000044D9 66891D[F06C0000] <1> mov [u.intr], bx 21125 <1> ; jsr r0,arg; u.intr / put the argument in u.intr 21126 <1> ; br 1f / go into quit routine 21127 000044E0 E9A0ECFFFF <1> jmp sysret 21128 <1> 21129 <1> sysquit: 21130 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 21131 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 21132 <1> ; 21133 <1> ; 'sysquit' turns off the quit signal. it puts the argument of 21134 <1> ; the call in u.quit. u.tty is checked if to see if a control 21135 <1> ; tty exists. If one does the interrupt character in the tty 21136 <1> ; buffer is cleared and 'sysret'is called. If one does not exits 21137 <1> ; 'sysret' is just called. 21138 <1> ; 21139 <1> ; Calling sequence: 21140 <1> ; sysquit; arg 21141 <1> ; Argument: 21142 <1> ; arg - if 0, this call disables quit signals from the 21143 <1> ; typewriter (ASCII FS) 21144 <1> ; - if 1, quits are re-enabled and cause execution to 21145 <1> ; cease and a core image to be produced. 21146 <1> ; i.e force an exit. 21147 <1> ; - if arg is an address in the program, 21148 <1> ; a quit causes control to sent to that 21149 <1> ; location. 21150 <1> ; Inputs: - 21151 <1> ; Outputs: - 21152 <1> ; ............................................................... 21153 <1> ; 21154 <1> ; Retro UNIX 8086 v1 modification: 21155 <1> ; 'sysquit' system call sets u.quit to value of BX 21156 <1> ; then branches into 'sysret'. 21157 <1> ; 21158 000044E5 66891D[F26C0000] <1> mov [u.quit], bx 21159 000044EC E994ECFFFF <1> jmp sysret 21160 <1> ; jsr r0,arg; u.quit / put argument in u.quit 21161 <1> ;1: 21162 <1> ; mov u.ttyp,r1 / move pointer to control tty buffer 21163 <1> ; / to r1 21164 <1> ; beq sysret4 / return to user 21165 <1> ; clrb 6(r1) / clear the interrupt character 21166 <1> ; / in the tty buffer 21167 <1> ; br sysret4 / return to user 21168 <1> 21169 <1> syssetuid: ; / set process id 21170 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 21171 <1> ; 27/03/2021 - Retro UNIX 386 v2 21172 <1> ; (16 bit uid) 21173 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 21174 <1> ; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1) 21175 <1> ; 21176 <1> ; 'syssetuid' sets the user id (u.uid) of the current process 21177 <1> ; to the process id in (u.r0). Both the effective user u.uid 21178 <1> ; and the real user u.ruid are set to this. 21179 <1> ; Only the super user can make this call. 21180 <1> ; 21181 <1> ; Calling sequence: 21182 <1> ; syssetuid 21183 <1> ; Arguments: - 21184 <1> ; 21185 <1> ; Inputs: (u.r0) - contains the process id. 21186 <1> ; Outputs: - 21187 <1> ; ............................................................... 21188 <1> ; 21189 <1> ; Retro UNIX 8086 v1 modification: 21190 <1> ; BL contains the (new) user ID of the current process 21191 <1> 21192 <1> ; 27/03/2021 21193 <1> ; INPUT: 21194 <1> ; BX = (new) user ID 21195 <1> 21196 <1> ; movb *u.r0,r1 / move process id (number) to r1 21197 <1> ;cmp bl, [u.ruid] 21198 <1> ; ; cmpb r1,u.ruid / is it equal to the real user 21199 <1> ; / id number 21200 <1> ; 27/03/2021 21201 000044F1 663B1D[F86C0000] <1> cmp bx, [u.ruid] 21202 000044F8 7420 <1> je short setuid1 21203 <1> ; beq 1f / yes 21204 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 21205 <1> ; ; tstb u.uid / no, is current user the super user? 21206 <1> ;;ja error 21207 <1> ; ; bne error4 / no, error 21208 <1> ; 27/03/2021 21209 000044FA 66833D[F66C0000]00 <1> cmp word [u.uid], 0 21210 00004502 760F <1> jna short setuid0 21211 <1> setuid_err: 21212 <1> setgid_err: 21213 00004504 C705[186D0000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 21214 0000450C 0000 <1> 21215 <1> ; 'permission denied !' error 21216 0000450E E952ECFFFF <1> jmp error 21217 <1> setuid0: 21218 <1> ;mov [u.ruid], bl 21219 <1> ; 27/03/2021 21220 00004513 66891D[F86C0000] <1> mov [u.ruid], bx 21221 <1> setuid1: ; 1: 21222 <1> ;mov [u.uid], bl ; 02/08/2013 21223 <1> ; ; movb r1,u.uid / put process id in u.uid 21224 <1> ; ; movb r1,u.ruid / put process id in u.ruid 21225 <1> ; 27/03/2021 21226 0000451A 66891D[F66C0000] <1> mov [u.uid], bx 21227 00004521 E95FECFFFF <1> jmp sysret 21228 <1> ; br sysret4 / system return 21229 <1> 21230 <1> sysgetuid: ; < get user id > 21231 <1> ; 11/03/2022 21232 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 21233 <1> ; 27/03/2021 - Retro UNIX 386 v2 21234 <1> ; (16 bit uid) 21235 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 21236 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 21237 <1> ; 21238 <1> ; 'sysgetuid' returns the real user ID of the current process. 21239 <1> ; The real user ID identifies the person who is logged in, 21240 <1> ; in contradistinction to the effective user ID, which 21241 <1> ; determines his access permission at each moment. It is thus 21242 <1> ; useful to programs which operate using the 'set user ID' 21243 <1> ; mode, to find out who invoked them. 21244 <1> ; 21245 <1> ; Calling sequence: 21246 <1> ; syssetuid 21247 <1> ; Arguments: - 21248 <1> ; 21249 <1> ; Inputs: - 21250 <1> ; Outputs: (u.r0) - contains the real user's id. 21251 <1> ; ............................................................... 21252 <1> ; 21253 <1> ; Retro UNIX 8086 v1 modification: 21254 <1> ; AL contains the real user ID at return. 21255 <1> ; 21256 <1> ; 11/03/2022 - Retro UNIX 386 v1.2 21257 <1> ; Input: 21258 <1> ; none 21259 <1> ; Output/Return: 21260 <1> ; AX = real user ID 21261 <1> ; Hig Word of EAX = effective user ID 21262 <1> 21263 <1> ;;movzx eax, byte [u.ruid] 21264 <1> ; 27/03/2021 21265 <1> ;movzx eax, word [u.ruid] 21266 <1> ; 11/03/2022 21267 <1> ; (return u.uid & u.ruid numbers as it is in unix v5-v7) 21268 00004526 66A1[F66C0000] <1> mov ax, [u.uid] 21269 0000452C C1E010 <1> shl eax, 16 ; efective user ID in high word of eax 21270 <1> ; 09/01/2022 21271 0000452F 66A1[F86C0000] <1> mov ax, [u.ruid] ; real user ID in low word of eax 21272 00004535 A3[A46C0000] <1> mov [u.r0], eax 21273 <1> ; movb u.ruid,*u.r0 / move the real user id to (u.r0) 21274 0000453A E946ECFFFF <1> jmp sysret 21275 <1> ; br sysret4 / systerm return, sysret 21276 <1> 21277 <1> syssetgid: ; set group id 21278 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 21279 <1> ; 02/04/2021 21280 <1> ; 27/03/2021 - Retro UNIX 386 v2 21281 <1> ; 21282 <1> ; 'syssetgid' sets the user's group id (u.gid) 21283 <1> ; of the current process to the process id in (u.r0). 21284 <1> ; Both the effective user u.gid and the real user 21285 <1> ; u.rgid are set to this. 21286 <1> ; Only the super user can make this call. 21287 <1> 21288 <1> ; INPUT: 21289 <1> ; BL = (new) group ID 21290 <1> ; OUTPUT: 21291 <1> ; - 21292 <1> 21293 0000453F 3A1D[FB6C0000] <1> cmp bl, [u.rgid] 21294 00004545 7410 <1> je short setgid1 21295 <1> 21296 <1> ;cmp byte [u.uid], 0 21297 <1> ; 02/04/2021 21298 00004547 66833D[F66C0000]00 <1> cmp word [u.uid], 0 21299 0000454F 77B3 <1> ja short setgid_err 21300 <1> setgid0: 21301 00004551 881D[FB6C0000] <1> mov [u.rgid], bl 21302 <1> setgid1: ; 1: 21303 00004557 881D[FA6C0000] <1> mov [u.gid], bl 21304 0000455D E923ECFFFF <1> jmp sysret 21305 <1> 21306 <1> sysgetgid: ; < get group id > 21307 <1> ; 11/03/2022 21308 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 21309 <1> ; 27/03/2021 - Retro UNIX 386 v2 21310 <1> ; 21311 <1> ; 'sysgetgid' returns the real group ID of the current process. 21312 <1> ; The real group ID identifies the group of the person 21313 <1> ; who is logged in, in contradistinction to the effective 21314 <1> ; group ID, which determines his access permission at each moment. 21315 <1> ; It is thus useful to programs which operate using 21316 <1> ; the 'set group ID' mode, to find out the group of the user 21317 <1> ; who invoked them. 21318 <1> 21319 <1> ; 11/03/2022 - Retro UNIX 386 v1.2 21320 <1> ; Input: 21321 <1> ; none 21322 <1> ; Output/Return: 21323 <1> ; AL = real group ID 21324 <1> ; AH = effective group ID 21325 <1> 21326 <1> ;movzx eax, word [u.ruid] 21327 <1> ;; 09/01/2022 21328 <1> ;mov ax, [u.ruid] 21329 <1> ; 11/03/2022 21330 <1> ; (return u.gid & u.rgid numbers as it is in unix v5-v7) 21331 00004562 8A25[FA6C0000] <1> mov ah, [u.gid] ; efective group ID in byte 1 21332 00004568 A0[FB6C0000] <1> mov al, [u.rgid] ; real group ID in byte 0 21333 0000456D A3[A46C0000] <1> mov [u.r0], eax 21334 00004572 E90EECFFFF <1> jmp sysret 21335 <1> 21336 <1> sysver: ; get operating system version 21337 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 21338 <1> ; 18/06/2021 - Retro UNIX 386 v2 21339 <1> 21340 <1> ;VMAJOR equ 2 ; Retro UNIX 386 v2 21341 <1> ;VMINOR equ 0 ; Retro UNIX 386 v2.0 (v2.0.0) 21342 <1> ;CURRENT_VERSION equ (VMAJOR*256)+VMINOR 21343 <1> 21344 <1> ; 09/01/2022 21345 <1> VMAJOR equ 1 ; Retro UNIX 386 v1 21346 <1> VMINOR equ 2 ; Retro UNIX 386 v1.2 (v1.2.0) 21347 <1> CURRENT_VERSION equ (VMAJOR*256)+VMINOR 21348 <1> 21349 <1> ; 29/04/2016 - TRDOS 386 v2.0 21350 <1> ;mov dword [u.r0], 200h ; AH = major version, AL = minor version 21351 <1> ; 18/06/2021 21352 00004577 C705[A46C0000]0201- <1> mov dword [u.r0], CURRENT_VERSION ; (ah = 2, al = 0) 21353 0000457F 0000 <1> 21354 00004581 E9FFEBFFFF <1> jmp sysret 21355 <1> 21356 <1> anyi: 21357 <1> ; 18/07/2022 21358 <1> ; 26/03/2022 21359 <1> ; 13/03/2022 21360 <1> ; 12/03/2022 21361 <1> ; 09/01/2022 21362 <1> ; 02/01/2022 21363 <1> ; 01/01/2022 21364 <1> ; 27/12/2021 (Retro UNIX 386 v1.2) 21365 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 21366 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 21367 <1> ; 25/04/2013 (Retro UNIX 8086 v1) 21368 <1> ; 21369 <1> ; 'anyi' is called if a file deleted while open. 21370 <1> ; "anyi" checks to see if someone else has opened this file. 21371 <1> ; 21372 <1> ; INPUTS -> 21373 <1> ; r1 - contains an i-number 21374 <1> ; fsp - start of table containing open files 21375 <1> ; 21376 <1> ; OUTPUTS -> 21377 <1> ; "deleted" flag set in fsp entry of another occurrence of 21378 <1> ; this file and r2 points 1st word of this fsp entry. 21379 <1> ; if file not found - bit in i-node map is cleared 21380 <1> ; (i-node is freed) 21381 <1> ; all blocks related to i-node are freed 21382 <1> ; all flags in i-node are cleared 21383 <1> ; ((AX = R1)) input 21384 <1> ; 21385 <1> ; (Retro UNIX Prototype: 02/12/2012, UNIXCOPY.ASM) 21386 <1> ; 12/03/2022 21387 <1> ; ((Modified registers: eax, edx, ecx, ebx, esi, edi, ebp)) 21388 <1> ; 21389 <1> ; / r1 contains an i-number 21390 00004586 BB[14690000] <1> mov ebx, fsp 21391 <1> ; mov $fsp,r2 / move start of fsp table to r2 21392 <1> anyi_1: ; 1: 21393 <1> ;cmp eax, [ebx] ; 09/01/2022 (32 bit inode number) 21394 0000458B 663B03 <1> cmp ax, [ebx] 21395 <1> ; cmp r1,(r2) / do i-numbers match? 21396 <1> ;je short anyi_3 21397 <1> ; beq 1f / yes, 1f 21398 <1> ; 12/03/2022 21399 0000458E 7505 <1> jne short anyi_0 21400 <1> 21401 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 21402 <1> ;neg ax 21403 <1> ; ; neg r1 / no complement r1 21404 <1> ;cmp ax, [ebx] 21405 <1> ; ; cmp r1,(r2) / do they match now? 21406 <1> ;;je short anyi_3 21407 <1> ; beq 1f / yes, transfer 21408 <1> ; / i-numbers do not match 21409 <1> ; 12/03/2022 21410 <1> ;jne short ayni_0 21411 <1> 21412 <1> anyi_3: ; 1: / i-numbers match 21413 <1> ; 13/03/2022 (BugFix) 21414 <1> ;; 09/01/2022 21415 <1> ;test byte [ebx+5], 1 ; open for writing flag 21416 <1> ;jz short anyi_0 21417 <1> 21418 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 21419 00004590 804B0580 <1> or byte [ebx+5], 80h ; set deleted file flag (bit 7) 21420 <1> ; 22/06/2015 21421 <1> ;inc byte [ebx+9] 21422 <1> ; incb 7(r2) / increment upper byte of the 4th word 21423 <1> ; / in that fsp entry (deleted flag of fsp entry) 21424 00004594 C3 <1> retn 21425 <1> ; rts r0 21426 <1> anyi_0: 21427 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 21428 <1> ;add ebx, fp.size ; runix v2 fsp table size is 16 bytes 21429 <1> ; 01/01/2022 21430 00004595 83C310 <1> add ebx, 16 ; runix v2 fsp table size is 16 bytes 21431 <1> ;;add ebx, 10 ; fsp table size is 10 bytes 21432 <1> ; in Retro UNIX 386 v1 (22/06/2015) 21433 <1> ; add $8,r2 / no, bump to next entry in fsp table 21434 <1> ; 22/11/2021 21435 <1> ;cmp ebx, fsp + (NFILES*fp.size) ; fsp+(NFILES*16) 21436 <1> ; 02/01/2022 21437 00004598 81FB[346C0000] <1> cmp ebx, fsp + (nfiles*16) 21438 <1> ; 01/01/2022 21439 <1> ;cmp ebx, fsp + (NFILES*16) ; fsp+(NFILES*fp.size) 21440 <1> ;;cmp ebx, fsp + (nfiles*10) ; 22/06/2015 21441 <1> ; cmp r2,$fsp+[nfiles*8] 21442 <1> ; / are we at last entry in the table 21443 0000459E 72EB <1> jb short anyi_1 21444 <1> ; blt 1b / no, check next entries i-number 21445 <1> 21446 <1> ; 27/12/2021 21447 <1> ;;cmp ax, 32768 21448 <1> ;cmp ah, 80h ; negative number check 21449 <1> ; ; tst r1 / yes, no match 21450 <1> ; ; bge .+4 21451 <1> ;jb short anyi_2 21452 <1> ;neg ax 21453 <1> ; ; neg r1 / make i-number positive 21454 <1> ;anyi_2: 21455 <1> ; 12/03/2022 21456 <1> ;push eax ; **** ; inode number 21457 <1> ; 21458 000045A0 E8AF080000 <1> call imap 21459 <1> ; jsr r0,imap / get address of allocation bit 21460 <1> ; / in the i-map in r2 21461 <1> 21462 <1> ;; DL/DX (MQ) has a 1 in the calculated bit position 21463 <1> ;; EBX (R2) has address of the byte with allocation bit 21464 <1> 21465 <1> ; 12/03/2022 21466 <1> ; (at return of imap) 21467 <1> ; ebp = superblock buffer address 21468 <1> ; eax = inode number 21469 <1> ; [ebp+SB.ImapBuffer] = physical block/sector number 21470 <1> ; of current IMAP sector 21471 <1> ; EBX = buffer address/offset for relevant alloc byte 21472 <1> ; DL has 1 at bit position which is for free inode 21473 <1> ; 21474 <1> ; ECX = byte offset from the (start of) inode map buffer 21475 <1> 21476 <1> ;;not dx 21477 <1> ;not dl ; 0 at calculated bit position, other bits are 1 21478 <1> ;;and [ebx], dx 21479 <1> ;and [ebx], dl 21480 <1> ; ; bicb mq,(r2) / clear bit for i-node in the imap 21481 <1> 21482 <1> ; 12/03/2022 ; (*) 21483 <1> 21484 <1> ;mov [ebp+SB.LastInode], eax ; (free) inode number 21485 <1> 21486 000045A5 50 <1> push eax ; *** 21487 000045A6 51 <1> push ecx ; ** 21488 000045A7 52 <1> push edx ; * 21489 <1> 21490 <1> ; 18/07/2022 21491 <1> ;push ebp ; @ ; 11/03/2022 21492 <1> 21493 000045A8 8B457C <1> mov eax, [ebp+SB.ImapBuffer] 21494 <1> 21495 000045AB E844140000 <1> call wslot 21496 <1> ; ebx = buffer data address (write operation bit is set) 21497 <1> ; eax = physical sector number 21498 <1> ; Note: ebx contains addr of the 1st buffer in the buf chain 21499 <1> ; (the last allocated buffer becomes the 1st in buffer chain) 21500 <1> 21501 <1> ; 18/07/2022 21502 <1> ;pop ebp ; @ ; 11/03/2022 21503 <1> 21504 <1> ;mov [ebp+SB.ImapBuffer], ebx 21505 <1> ; save inode map buffer address 21506 000045B0 5A <1> pop edx ; * 21507 000045B1 59 <1> pop ecx ; ** 21508 000045B2 01CB <1> add ebx, ecx ; + byte offset (for allocation bit pos) 21509 <1> 21510 <1> ;not dx 21511 000045B4 F6D2 <1> not dl ; 0 at calculated bit position, other bits are 1 21512 <1> ;and [ebx], dx 21513 000045B6 2013 <1> and [ebx], dl 21514 <1> ; bicb mq,(r2) / clear bit for i-node in the imap 21515 <1> 21516 <1> ;push ebp ; @ 21517 000045B8 E844140000 <1> call dskwr ; writes the 1st buffer to sector 21518 <1> ; (at the beginning/head of the buffer chain) 21519 <1> ;pop ebp ; @ 21520 <1> 21521 <1> ; if we are here, buffer has been written to disk successfully 21522 <1> ; (otherwise cpu would jump to 'error' address) 21523 <1> 21524 <1> ; 12/03/2022 ; (*) 21525 <1> ; set superblock modified flag 21526 000045BD BA[966C0000] <1> mov edx, smod 21527 000045C2 F605[816C0000]01 <1> test byte [cdev], 1 ; mounted device ? 21528 000045C9 7401 <1> jz short anyi_2 ; no, root device 21529 <1> ; yes, mounted device 21530 000045CB 42 <1> inc edx ; edx = offset mmod 21531 <1> anyi_2: 21532 000045CC FE02 <1> inc byte [edx] ; superblock modified ! 21533 <1> 21534 <1> ; 12/03/2022 21535 <1> ; decrease first free inode number (if it is required) 21536 000045CE 8B0424 <1> mov eax, [esp] ; *** 21537 <1> ; eax = released/freed inode number 21538 000045D1 394534 <1> cmp [ebp+SB.FirstFreeIno], eax 21539 000045D4 7603 <1> jna short anyi_4 21540 000045D6 894534 <1> mov [ebp+SB.FirstFreeIno], eax 21541 <1> ; (free inode search start value) 21542 <1> anyi_4: 21543 <1> ; 12/03/2022 21544 <1> ; increase free inode count 21545 000045D9 8B5530 <1> mov edx, [ebp+SB.FreeInodes] 21546 <1> ;cmp edx, 0FFFFFFFFh 21547 <1> ;je short anyi_5 ; invalid 21548 000045DC 42 <1> inc edx ; 0FFFFFFFFh -> 0 21549 000045DD 7403 <1> jz short anyi_5 ; invalid 21550 000045DF 895530 <1> mov [ebp+SB.FreeInodes], edx ; +1 21551 <1> anyi_5: 21552 000045E2 E870150000 <1> call get_system_time 21553 <1> ; eax = current time (as unix epoch time) 21554 000045E7 89455C <1> mov [ebp+SB.ModifTime], eax 21555 <1> 21556 000045EA 58 <1> pop eax ; *** ; inode number 21557 <1> 21558 000045EB E860070000 <1> call itrunc 21559 <1> ; jsr r0,itrunc / free all blocks related to i-node 21560 <1> 21561 <1> ; 26/03/2022 21562 <1> ; eax = 0 ; (itrunc clears eax at return) 21563 <1> 21564 <1> ; 12/03/2022 21565 <1> ;pop eax ; **** ; inode number 21566 <1> 21567 <1> ; 26/03/2022 21568 000045F0 66A3[24680000] <1> mov [i.flgs], ax ; (eax should be 0 here) 21569 <1> ;mov word [i.flgs], 0 21570 <1> ; clr i.flgs / clear all flags in the i-node 21571 000045F6 C3 <1> retn 21572 <1> ; rts r0 / return 21573 <1> 21574 <1> ;anyi_3: ; 1: / i-numbers match 21575 <1> ; ; 09/01/2022 21576 <1> ; test byte [ebx+5], 1 ; open for writing flag 21577 <1> ; jz short anyi_0 21578 <1> ; 21579 <1> ; ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 21580 <1> ; or byte [ebx+5], 80h ; set deleted file flag (bit 7) 21581 <1> ; ; 22/06/2015 21582 <1> ; ;inc byte [ebx+9] 21583 <1> ; ; incb 7(r2) / increment upper byte of the 4th word 21584 <1> ; ; / in that fsp entry (deleted flag of fsp entry) 21585 <1> ; retn 21586 <1> ; ; rts r0 21587 %include 'u3.s' ; 10/05/2015 21588 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 21589 <1> ; (re-write kernel for test by using previous version without a major defect) 21590 <1> ; **************************************************************************** 21591 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC 21592 <1> ; Last Modification: 24/12/2021 21593 <1> ; ---------------------------------------------------------------------------- 21594 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 21595 <1> ; (v0.1 - Beginning: 11/07/2012) 21596 <1> ; 21597 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 21598 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 21599 <1> ; 21600 <1> ; 21601 <1> ; 21602 <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s 21603 <1> ; 21604 <1> ; **************************************************************************** 21605 <1> 21606 <1> tswitch: ; Retro UNIX 386 v1 21607 <1> tswap: 21608 <1> ; 01/09/2015 21609 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 21610 <1> ; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 21611 <1> ; time out swap, called when a user times out. 21612 <1> ; the user is put on the low priority queue. 21613 <1> ; This is done by making a link from the last user 21614 <1> ; on the low priority queue to him via a call to 'putlu'. 21615 <1> ; then he is swapped out. 21616 <1> ; 21617 <1> ; Retro UNIX 386 v1 modification -> 21618 <1> ; swap (software task switch) is performed by changing 21619 <1> ; user's page directory (u.pgdir) instead of segment change 21620 <1> ; as in Retro UNIX 8086 v1. 21621 <1> ; 21622 <1> ; RETRO UNIX 8086 v1 modification -> 21623 <1> ; 'swap to disk' is replaced with 'change running segment' 21624 <1> ; according to 8086 cpu (x86 real mode) architecture. 21625 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 21626 <1> ; compatibles was using 1MB segmented memory 21627 <1> ; in 8086/8088 times. 21628 <1> ; 21629 <1> ; INPUTS -> 21630 <1> ; u.uno - users process number 21631 <1> ; runq+4 - lowest priority queue 21632 <1> ; OUTPUTS -> 21633 <1> ; r0 - users process number 21634 <1> ; r2 - lowest priority queue address 21635 <1> ; 21636 <1> ; ((AX = R0, BX = R2)) output 21637 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) 21638 <1> ; 21639 000045F7 A0[F56C0000] <1> mov al, [u.uno] 21640 <1> ; movb u.uno,r1 / move users process number to r1 21641 <1> ; mov $runq+4,r2 21642 <1> ; / move lowest priority queue address to r2 21643 000045FC E8CD000000 <1> call putlu 21644 <1> ; jsr r0,putlu / create link from last user on Q to 21645 <1> ; / u.uno's user 21646 <1> 21647 <1> switch: ; Retro UNIX 386 v1 21648 <1> swap: 21649 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 21650 <1> ; 02/09/2015 21651 <1> ; 01/09/2015 21652 <1> ; 31/08/2015 21653 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 21654 <1> ; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1) 21655 <1> ; 'swap' is routine that controls the swapping of processes 21656 <1> ; in and out of core. 21657 <1> ; 21658 <1> ; Retro UNIX 386 v1 modification -> 21659 <1> ; swap (software task switch) is performed by changing 21660 <1> ; user's page directory (u.pgdir) instead of segment change 21661 <1> ; as in Retro UNIX 8086 v1. 21662 <1> ; 21663 <1> ; RETRO UNIX 8086 v1 modification -> 21664 <1> ; 'swap to disk' is replaced with 'change running segment' 21665 <1> ; according to 8086 cpu (x86 real mode) architecture. 21666 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 21667 <1> ; compatibles was using 1MB segmented memory 21668 <1> ; in 8086/8088 times. 21669 <1> ; 21670 <1> ; INPUTS -> 21671 <1> ; runq table - contains processes to run. 21672 <1> ; p.link - contains next process in line to be run. 21673 <1> ; u.uno - process number of process in core 21674 <1> ; s.stack - swap stack used as an internal stack for swapping. 21675 <1> ; OUTPUTS -> 21676 <1> ; (original unix v1 -> present process to its disk block) 21677 <1> ; (original unix v1 -> new process into core -> 21678 <1> ; Retro Unix 8086 v1 -> segment registers changed 21679 <1> ; for new process) 21680 <1> ; u.quant = 3 (Time quantum for a process) 21681 <1> ; ((INT 1Ch count down speed -> 18.2 times per second) 21682 <1> ; RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second) 21683 <1> ; for now, it will swap the process if there is not 21684 <1> ; a keyboard event (keystroke) (Int 15h, function 4Fh) 21685 <1> ; or will count down from 3 to 0 even if there is a 21686 <1> ; keyboard event locking due to repetitive key strokes. 21687 <1> ; u.quant will be reset to 3 for RETRO UNIX 8086 v1. 21688 <1> ; 21689 <1> ; u.pri -points to highest priority run Q. 21690 <1> ; r2 - points to the run queue. 21691 <1> ; r1 - contains new process number 21692 <1> ; r0 - points to place in routine or process that called 21693 <1> ; swap all user parameters 21694 <1> ; 21695 <1> ; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI)) 21696 <1> ; 21697 <1> swap_0: 21698 <1> ;mov $300,*$ps / processor priority = 6 21699 00004601 BE[926C0000] <1> mov esi, runq 21700 <1> ; mov $runq,r2 / r2 points to runq table 21701 <1> swap_1: ; 1: / search runq table for highest priority process 21702 00004606 668B06 <1> mov ax, [esi] 21703 00004609 6621C0 <1> and ax, ax 21704 <1> ; tst (r2)+ / are there any processes to run 21705 <1> ; / in this Q entry 21706 0000460C 7507 <1> jnz short swap_2 21707 <1> ; bne 1f / yes, process 1f 21708 <1> ; cmp r2,$runq+6 / if zero compare address 21709 <1> ; / to end of table 21710 <1> ; bne 1b / if not at end, go back 21711 0000460E E8E0000000 <1> call idle 21712 <1> ; jsr r0,idle; s.idlet+2 / wait for interrupt; 21713 <1> ; / all queues are empty 21714 00004613 EBF1 <1> jmp short swap_1 21715 <1> ; br swap 21716 <1> swap_2: ; 1: 21717 00004615 0FB6D8 <1> movzx ebx, al ; 02/09/2015 21718 <1> ; tst -(r2) / restore pointer to right Q entry 21719 <1> ; mov r2,u.pri / set present user to this run queue 21720 <1> ; movb (r2)+,r1 / move 1st process in queue to r1 21721 00004618 38E0 <1> cmp al, ah 21722 <1> ; cmpb r1,(r2)+ / is there only 1 process 21723 <1> ; / in this Q to be run 21724 0000461A 740A <1> je short swap_3 21725 <1> ; beq 1f / yes 21726 <1> ; tst -(r2) / no, pt r2 back to this Q entry 21727 <1> ;movzx ebx, al 21728 0000461C 8AA3[B3680000] <1> mov ah, [ebx+p.link-1] 21729 00004622 8826 <1> mov [esi], ah 21730 <1> ; movb p.link-1(r1),(r2) / move next process 21731 <1> ; / in line into run queue 21732 00004624 EB05 <1> jmp short swap_4 21733 <1> ; br 2f 21734 <1> swap_3: ; 1: 21735 <1> ;xor dx, dx 21736 <1> ; 24/12/2021 21737 00004626 31D2 <1> xor edx, edx 21738 00004628 668916 <1> mov [esi], dx 21739 <1> ; clr -(r2) / zero the entry; no processes on the Q 21740 <1> swap_4: ; / write out core to appropriate disk area and read 21741 <1> ; / in new process if required 21742 <1> ; clr *$ps / clear processor status 21743 0000462B 8A25[F56C0000] <1> mov ah, [u.uno] 21744 00004631 38C4 <1> cmp ah, al 21745 <1> ; cmpb r1,u.uno / is this process the same as 21746 <1> ; / the process in core? 21747 00004633 743B <1> je short swap_8 21748 <1> ; beq 2f / yes, don't have to swap 21749 <1> ; mov r0,-(sp) / no, write out core; save r0 21750 <1> ; / (address in routine that called swap) 21751 <1> ; mov r1,-(sp) / put r1 (new process #) on the stack 21752 <1> ; 01/09/2015 21753 <1> ;mov [u.usp], esp 21754 <1> ; mov sp,u.usp / save stack pointer 21755 <1> ; mov $sstack,sp / move swap stack pointer 21756 <1> ; / to the stack pointer 21757 00004635 08E4 <1> or ah, ah 21758 <1> ; tstb u.uno / is the process # = 0 21759 00004637 740D <1> jz short swap_6 ; 'sysexit' 21760 <1> ; beq 1f / yes, kill process by overwriting 21761 <1> ; 02/09/2015 21762 00004639 8925[A06C0000] <1> mov [u.usp], esp ; return address for 'syswait' & 'sleep' 21763 <1> ; 21764 0000463F E834000000 <1> call wswap 21765 <1> ;jsr r0,wswap / write out core to disk 21766 <1> ; 31/08/2015 21767 <1> ;movzx ebx, al ; New (running) process number 21768 00004644 EB1C <1> jmp short swap_7 21769 <1> swap_6: 21770 <1> ; 31/08/2015 21771 <1> ; Deallocate memory pages belong to the process 21772 <1> ; which is being terminated 21773 <1> ; 14/05/2015 ('sysexit') 21774 <1> ; Deallocate memory pages of the process 21775 <1> ; (Retro UNIX 386 v1 modification !) 21776 <1> ; 21777 <1> ; movzx ebx, al 21778 00004646 53 <1> push ebx 21779 00004647 A1[046D0000] <1> mov eax, [u.pgdir] ; page directory of the process 21780 0000464C 8B1D[086D0000] <1> mov ebx, [u.ppgdir] ; page directory of the parent process 21781 00004652 E8B8DEFFFF <1> call deallocate_page_dir 21782 00004657 A1[006D0000] <1> mov eax, [u.upage] ; 'user' structure page of the process 21783 0000465C E844DFFFFF <1> call deallocate_page 21784 00004661 5B <1> pop ebx 21785 <1> swap_7: ;1: 21786 <1> ; 02/09/2015 21787 <1> ; 31/08/2015 21788 <1> ; 14/05/2015 21789 00004662 C0E302 <1> shl bl, 2 ; * 4 21790 00004665 8B83[D0680000] <1> mov eax, [ebx+p.upage-4] ; the 'u' page of the new process 21791 <1> ;cli 21792 0000466B E831000000 <1> call rswap 21793 <1> ; mov (sp)+,r1 / restore r1 to new process number 21794 <1> ; jsr r0,rswap / read new process into core 21795 <1> ; jsr r0,unpack / unpack the users stack from next 21796 <1> ; / to his program to its normal 21797 <1> ; 01/09/2015 21798 <1> ;mov esp, [u.usp] 21799 <1> ; mov u.usp,sp / location; restore stack pointer to 21800 <1> ; / new process stack 21801 <1> ; mov (sp)+,r0 / put address of where the process 21802 <1> ; / that just got swapped in, left off., 21803 <1> ; / i.e., transfer control to new process 21804 <1> ;sti 21805 <1> swap_8: ;2: 21806 <1> ; RETRO UNIX 8086 v1 modification ! 21807 00004670 C605[EC6C0000]04 <1> mov byte [u.quant], time_count 21808 <1> ; movb $30.,uquant / initialize process time quantum 21809 00004677 C3 <1> retn 21810 <1> ; rts r0 / return 21811 <1> 21812 <1> wswap: ; < swap out, swap to disk > 21813 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 21814 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 21815 <1> ; 'wswap' writes out the process that is in core onto its 21816 <1> ; appropriate disk area. 21817 <1> ; 21818 <1> ; Retro UNIX 386 v1 modification -> 21819 <1> ; User (u) structure content and the user's register content 21820 <1> ; will be copied to the process's/user's UPAGE (a page for 21821 <1> ; saving 'u' structure and user registers for task switching). 21822 <1> ; u.usp - points to kernel stack address which contains 21823 <1> ; user's registers while entering system call. 21824 <1> ; u.sp - points to kernel stack address 21825 <1> ; to return from system call -for IRET-. 21826 <1> ; [u.usp]+32+16 = [u.sp] 21827 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 21828 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 21829 <1> ; 21830 <1> ; Retro UNIX 8086 v1 modification -> 21831 <1> ; 'swap to disk' is replaced with 'change running segment' 21832 <1> ; according to 8086 cpu (x86 real mode) architecture. 21833 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 21834 <1> ; compatibles was using 1MB segmented memory 21835 <1> ; in 8086/8088 times. 21836 <1> ; 21837 <1> ; INPUTS -> 21838 <1> ; u.break - points to end of program 21839 <1> ; u.usp - stack pointer at the moment of swap 21840 <1> ; core - beginning of process program 21841 <1> ; ecore - end of core 21842 <1> ; user - start of user parameter area 21843 <1> ; u.uno - user process number 21844 <1> ; p.dska - holds block number of process 21845 <1> ; OUTPUTS -> 21846 <1> ; swp I/O queue 21847 <1> ; p.break - negative word count of process 21848 <1> ; r1 - process disk address 21849 <1> ; r2 - negative word count 21850 <1> ; 21851 <1> ; RETRO UNIX 8086 v1 input/output: 21852 <1> ; 21853 <1> ; INPUTS -> 21854 <1> ; u.uno - process number (to be swapped out) 21855 <1> ; OUTPUTS -> 21856 <1> ; none 21857 <1> ; 21858 <1> ; ((Modified registers: ECX, ESI, EDI)) 21859 <1> ; 21860 00004678 8B3D[006D0000] <1> mov edi, [u.upage] ; process's user (u) structure page addr 21861 0000467E B921000000 <1> mov ecx, (U_SIZE + 3) / 4 21862 00004683 BE[9C6C0000] <1> mov esi, user ; active user (u) structure 21863 00004688 F3A5 <1> rep movsd 21864 <1> ; 21865 0000468A 8B35[A06C0000] <1> mov esi, [u.usp] ; esp (system stack pointer, 21866 <1> ; points to user registers) 21867 00004690 8B0D[9C6C0000] <1> mov ecx, [u.sp] ; return address from the system call 21868 <1> ; (for IRET) 21869 <1> ; [u.sp] -> EIP (user) 21870 <1> ; [u.sp+4]-> CS (user) 21871 <1> ; [u.sp+8] -> EFLAGS (user) 21872 <1> ; [u.sp+12] -> ESP (user) 21873 <1> ; [u.sp+16] -> SS (user) 21874 00004696 29F1 <1> sub ecx, esi ; required space for user registers 21875 00004698 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 21876 <1> ; (for IRET) 21877 0000469B C1E902 <1> shr ecx, 2 21878 0000469E F3A5 <1> rep movsd 21879 000046A0 C3 <1> retn 21880 <1> 21881 <1> ; Original UNIX v1 'wswap' routine: 21882 <1> ; wswap: 21883 <1> ; mov *$30,u.emt / determines handling of emts 21884 <1> ; mov *$10,u.ilgins / determines handling of 21885 <1> ; / illegal instructions 21886 <1> ; mov u.break,r2 / put process program break address in r2 21887 <1> ; inc r2 / add 1 to it 21888 <1> ; bic $1,r2 / make it even 21889 <1> ; mov r2,u.break / set break to an even location 21890 <1> ; mov u.usp,r3 / put users stack pointer 21891 <1> ; / at moment of swap in r3 21892 <1> ; cmp r2,$core / is u.break less than $core 21893 <1> ; blos 2f / yes 21894 <1> ; cmp r2,r3 / no, is (u.break) greater than stack ptr. 21895 <1> ; bhis 2f / yes 21896 <1> ; 1: 21897 <1> ; mov (r3)+,(r2)+ / no, pack stack next to users program 21898 <1> ; cmp r3,$ecore / has stack reached end of core 21899 <1> ; bne 1b / no, keep packing 21900 <1> ; br 1f / yes 21901 <1> ; 2: 21902 <1> ; mov $ecore,r2 / put end of core in r2 21903 <1> ; 1: 21904 <1> ; sub $user,r2 / get number of bytes to write out 21905 <1> ; / (user up to end of stack gets written out) 21906 <1> ; neg r2 / make it negative 21907 <1> ; asr r2 / change bytes to words (divide by 2) 21908 <1> ; mov r2,swp+4 / word count 21909 <1> ; movb u.uno,r1 / move user process number to r1 21910 <1> ; asl r1 / x2 for index 21911 <1> ; mov r2,p.break-2(r1) / put negative of word count 21912 <1> ; / into the p.break table 21913 <1> ; mov p.dska-2(r1),r1 / move disk address of swap area 21914 <1> ; / for process to r1 21915 <1> ; mov r1,swp+2 / put processes dska address in swp+2 21916 <1> ; / (block number) 21917 <1> ; bis $1000,swp / set it up to write (set bit 9) 21918 <1> ; jsr r0,ppoke / write process out on swap area of disk 21919 <1> ; 1: 21920 <1> ; tstb swp+1 / is lt done writing? 21921 <1> ; bne 1b / no, wait 21922 <1> ; rts r0 / yes, return to swap 21923 <1> 21924 <1> rswap: ; < swap in, swap from disk > 21925 <1> ; 15/09/2015 21926 <1> ; 28/08/2015 21927 <1> ; 14/05/2015 21928 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 21929 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 21930 <1> ; 'rswap' reads a process whose number is in r1, 21931 <1> ; from disk into core. 21932 <1> ; 21933 <1> ; Retro UNIX 386 v1 modification -> 21934 <1> ; User (u) structure content and the user's register content 21935 <1> ; will be restored from process's/user's UPAGE (a page for 21936 <1> ; saving 'u' structure and user registers for task switching). 21937 <1> ; u.usp - points to kernel stack address which contains 21938 <1> ; user's registers while entering system call. 21939 <1> ; u.sp - points to kernel stack address 21940 <1> ; to return from system call -for IRET-. 21941 <1> ; [u.usp]+32+16 = [u.sp] 21942 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 21943 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 21944 <1> ; 21945 <1> ; RETRO UNIX 8086 v1 modification -> 21946 <1> ; 'swap to disk' is replaced with 'change running segment' 21947 <1> ; according to 8086 cpu (x86 real mode) architecture. 21948 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 21949 <1> ; compatibles was using 1MB segmented memory 21950 <1> ; in 8086/8088 times. 21951 <1> ; 21952 <1> ; INPUTS -> 21953 <1> ; r1 - process number of process to be read in 21954 <1> ; p.break - negative of word count of process 21955 <1> ; p.dska - disk address of the process 21956 <1> ; u.emt - determines handling of emt's 21957 <1> ; u.ilgins - determines handling of illegal instructions 21958 <1> ; OUTPUTS -> 21959 <1> ; 8 = (u.ilgins) 21960 <1> ; 24 = (u.emt) 21961 <1> ; swp - bit 10 is set to indicate read 21962 <1> ; (bit 15=0 when reading is done) 21963 <1> ; swp+2 - disk block address 21964 <1> ; swp+4 - negative word count 21965 <1> ; ((swp+6 - address of user structure)) 21966 <1> ; 21967 <1> ; RETRO UNIX 8086 v1 input/output: 21968 <1> ; 21969 <1> ; INPUTS -> 21970 <1> ; AL - new process number (to be swapped in) 21971 <1> ; OUTPUTS -> 21972 <1> ; none 21973 <1> ; 21974 <1> ; ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 21975 <1> ; 21976 <1> ; Retro UNIX 386 v1 - modification ! 14/05/2015 21977 000046A1 89C6 <1> mov esi, eax ; process's user (u) structure page addr 21978 000046A3 B921000000 <1> mov ecx, (U_SIZE + 3) / 4 21979 000046A8 BF[9C6C0000] <1> mov edi, user ; active user (u) structure 21980 000046AD F3A5 <1> rep movsd 21981 000046AF 58 <1> pop eax ; 15/09/2015, 'rswap' return address 21982 000046B0 8B3D[A06C0000] <1> mov edi, [u.usp] ; esp (system stack pointer, 21983 <1> ; points to user registers) 21984 000046B6 8B0D[9C6C0000] <1> mov ecx, [u.sp] ; return address from the system call 21985 <1> ; (for IRET) 21986 <1> ; [u.sp] -> EIP (user) 21987 <1> ; [u.sp+4]-> CS (user) 21988 <1> ; [u.sp+8] -> EFLAGS (user) 21989 <1> ; [u.sp+12] -> ESP (user) 21990 <1> ; [u.sp+16] -> SS (user) 21991 <1> ; 28/08/2015 21992 000046BC 29F9 <1> sub ecx, edi ; required space for user registers 21993 000046BE 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 21994 <1> ; (for IRET) 21995 000046C1 C1E902 <1> shr ecx, 2 21996 000046C4 F3A5 <1> rep movsd 21997 000046C6 8B25[A06C0000] <1> mov esp, [u.usp] ; 15/09/2015 21998 000046CC 50 <1> push eax ; 15/09/2015 'rswap' return address 21999 000046CD C3 <1> retn 22000 <1> 22001 <1> ; Original UNIX v1 'rswap' and 'unpack' routines: 22002 <1> ;rswap: 22003 <1> ; asl r1 / process number x2 for index 22004 <1> ; mov p.break-2(r1), swp+4 / word count 22005 <1> ; mov p.dska-2(r1),swp+2 / disk address 22006 <1> ; bis $2000,swp / read 22007 <1> ; jsr r0,ppoke / read it in 22008 <1> ; 1: 22009 <1> ; tstb swp+1 / done 22010 <1> ; bne 1b / no, wait for bit 15 to clear (inhibit bit) 22011 <1> ; mov u.emt,*$30 / yes move these 22012 <1> ; mov u.ilgins,*$10 / back 22013 <1> ; rts r0 / return 22014 <1> 22015 <1> ;unpack: ; / move stack back to its normal place 22016 <1> ; mov u.break,r2 / r2 points to end of user program 22017 <1> ; cmp r2,$core / at beginning of user program yet? 22018 <1> ; blos 2f / yes, return 22019 <1> ; cmp r2,u.usp / is break_above the stack pointer 22020 <1> ; / before swapping 22021 <1> ; bhis 2f / yes, return 22022 <1> ; mov $ecore,r3 / r3 points to end of core 22023 <1> ; add r3,r2 22024 <1> ; sub u.usp,r2 / end of users stack is in r2 22025 <1> ; 1: 22026 <1> ; mov -(r2),-(r3) / move stack back to its normal place 22027 <1> ; cmp r2,u.break / in core 22028 <1> ; bne 1b 22029 <1> ; 2: 22030 <1> ; rts r0 22031 <1> 22032 <1> putlu: 22033 <1> ; 12/09/2015 22034 <1> ; 02/09/2015 22035 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 22036 <1> ; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 22037 <1> ; 'putlu' is called with a process number in r1 and a pointer 22038 <1> ; to lowest priority Q (runq+4) in r2. A link is created from 22039 <1> ; the last process on the queue to process in r1 by putting 22040 <1> ; the process number in r1 into the last process's link. 22041 <1> ; 22042 <1> ; INPUTS -> 22043 <1> ; r1 - user process number 22044 <1> ; r2 - points to lowest priority queue 22045 <1> ; p.dska - disk address of the process 22046 <1> ; u.emt - determines handling of emt's 22047 <1> ; u.ilgins - determines handling of illegal instructions 22048 <1> ; OUTPUTS -> 22049 <1> ; r3 - process number of last process on the queue upon 22050 <1> ; entering putlu 22051 <1> ; p.link-1 + r3 - process number in r1 22052 <1> ; r2 - points to lowest priority queue 22053 <1> ; 22054 <1> ; ((Modified registers: EDX, EBX)) 22055 <1> ; 22056 <1> ; / r1 = user process no.; r2 points to lowest priority queue 22057 <1> 22058 <1> ; eBX = r2 22059 <1> ; eAX = r1 (AL=r1b) 22060 <1> 22061 000046CE BB[926C0000] <1> mov ebx, runq 22062 000046D3 0FB613 <1> movzx edx, byte [ebx] 22063 000046D6 43 <1> inc ebx 22064 000046D7 20D2 <1> and dl, dl 22065 <1> ; tstb (r2)+ / is queue empty? 22066 000046D9 740A <1> jz short putlu_1 22067 <1> ; beq 1f / yes, branch 22068 000046DB 8A13 <1> mov dl, [ebx] ; 12/09/2015 22069 <1> ; movb (r2),r3 / no, save the "last user" process number 22070 <1> ; / in r3 22071 000046DD 8882[B3680000] <1> mov [edx+p.link-1], al 22072 <1> ; movb r1,p.link-1(r3) / put pointer to user on 22073 <1> ; / "last users" link 22074 000046E3 EB03 <1> jmp short putlu_2 22075 <1> ; br 2f / 22076 <1> putlu_1: ; 1: 22077 000046E5 8843FF <1> mov [ebx-1], al 22078 <1> ; movb r1,-1(r2) / user is only user; 22079 <1> ; / put process no. at beginning and at end 22080 <1> putlu_2: ; 2: 22081 000046E8 8803 <1> mov [ebx], al 22082 <1> ; movb r1,(r2) / user process in r1 is now the last entry 22083 <1> ; / on the queue 22084 000046EA 88C2 <1> mov dl, al 22085 000046EC 88B2[B3680000] <1> mov [edx+p.link-1], dh ; 0 22086 <1> ; dec r2 / restore r2 22087 000046F2 C3 <1> retn 22088 <1> ; rts r0 22089 <1> 22090 <1> ;copyz: 22091 <1> ; mov r1,-(sp) / put r1 on stack 22092 <1> ; mov r2,-(sp) / put r2 on stack 22093 <1> ; mov (r0)+,r1 22094 <1> ; mov (r0)+,r2 22095 <1> ;1: 22096 <1> ; clr (r1)+ / clear all locations between r1 and r2 22097 <1> ; cmp r1,r2 22098 <1> ; blo 1b 22099 <1> ; mov (sp)+,r2 / restore r2 22100 <1> ; mov (sp)+,r1 / restore r1 22101 <1> ; rts r0 22102 <1> 22103 <1> idle: 22104 <1> ; 01/09/2015 22105 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 22106 <1> ; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1) 22107 <1> ; (idle & wait loop) 22108 <1> ; Retro Unix 8086 v1 modification on original UNIX v1 22109 <1> ; idle procedure! 22110 <1> ; 22111 <1> ; 01/09/2015 22112 000046F3 FB <1> sti 22113 <1> ; 29/07/2013 22114 000046F4 F4 <1> hlt 22115 000046F5 90 <1> nop ; 10/10/2013 22116 000046F6 90 <1> nop 22117 000046F7 90 <1> nop 22118 <1> ; 23/10/2013 22119 000046F8 90 <1> nop 22120 000046F9 90 <1> nop 22121 000046FA 90 <1> nop 22122 000046FB 90 <1> nop 22123 000046FC C3 <1> retn 22124 <1> 22125 <1> ;mov *$ps,-(sp) / save ps on stack 22126 <1> ;clr *$ps / clear ps 22127 <1> ;mov clockp,-(sp) / save clockp on stack 22128 <1> ;mov (r0)+,clockp / arg to idle in clockp 22129 <1> ;1 / wait for interrupt 22130 <1> ;mov (sp)+,clockp / restore clockp, ps 22131 <1> ;mov (sp)+,*$ps 22132 <1> ;rts r0 22133 <1> 22134 <1> clear: 22135 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 22136 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 22137 <1> ; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 22138 <1> ; 'clear' zero's out of a block (whose block number is in r1) 22139 <1> ; on the current device (cdev) 22140 <1> ; 22141 <1> ; INPUTS -> 22142 <1> ; r1 - block number of block to be zeroed 22143 <1> ; cdev - current device number 22144 <1> ; OUTPUTS -> 22145 <1> ; a zeroed I/O buffer onto the current device 22146 <1> ; r1 - points to last entry in the I/O buffer 22147 <1> ; 22148 <1> ; ((AX = R1)) input/output 22149 <1> ; (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM) 22150 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP)) 22151 <1> 22152 000046FD E8F2120000 <1> call wslot 22153 <1> ; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first 22154 <1> ; / word of I/O queue r5 points to first data word in buffer 22155 00004702 89DF <1> mov edi, ebx ; r5 22156 00004704 89C2 <1> mov edx, eax 22157 00004706 B980000000 <1> mov ecx, 128 22158 <1> ; mov $256.,r3 22159 0000470B 31C0 <1> xor eax, eax 22160 0000470D F3AB <1> rep stosd 22161 0000470F 89D0 <1> mov eax, edx 22162 <1> ; 1: 22163 <1> ; clr (r5)+ / zero data word in buffer 22164 <1> ; dec r3 22165 <1> ; bgt 1b / branch until all data words in buffer are zero 22166 <1> ;call dskwr 22167 <1> ; jsr r0,dskwr / write zeroed buffer area out onto physical 22168 <1> ; / block specified in r1 22169 <1> ; eAX (r1) = block number 22170 <1> ;retn 22171 <1> ; rts r0 22172 <1> ; 24/12/2021 22173 00004711 E9EB120000 <1> jmp dskwr 22174 %include 'u4.s' ; 15/04/2015 22175 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 22176 <1> ; (re-write kernel for test by using previous version without a major defect) 22177 <1> ; **************************************************************************** 22178 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC 22179 <1> ; Last Modification: 27/02/2022 (Retro UNIX 386 v1.2) 22180 <1> ; ---------------------------------------------------------------------------- 22181 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 22182 <1> ; (v0.1 - Beginning: 11/07/2012) 22183 <1> ; 22184 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 22185 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 22186 <1> ; 22187 <1> ; 22188 <1> ; 22189 <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s 22190 <1> ; 22191 <1> ; **************************************************************************** 22192 <1> 22193 <1> ;setisp: 22194 <1> ;mov r1,-(sp) 22195 <1> ;mov r2,-(sp) 22196 <1> ;mov r3,-(sp) 22197 <1> ;mov clockp,-(sp) 22198 <1> ;mov $s.syst+2,clockp 22199 <1> ;jmp (r0) 22200 <1> 22201 <1> clock: ; / interrupt from 60 cycle clock 22202 <1> 22203 <1> ; 14/10/2015 22204 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 22205 <1> ; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1) 22206 <1> 22207 <1> ;mov r0,-(sp) / save r0 22208 <1> ;tst *$lks / restart clock? 22209 <1> ;mov $s.time+2,r0 / increment the time of day 22210 <1> ;inc (r0) 22211 <1> ;bne 1f 22212 <1> ;inc -(r0) 22213 <1> ;1: 22214 <1> ;mov clockp,r0 / increment appropriate time category 22215 <1> ;inc (r0) 22216 <1> ;bne 1f 22217 <1> ;inc -(r0) 22218 <1> ;1: 22219 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22220 <1> 22221 00004716 803D[EC6C0000]00 <1> cmp byte [u.quant], 0 22222 0000471D 772C <1> ja short clk_1 22223 <1> ; 22224 0000471F 803D[986C0000]FF <1> cmp byte [sysflg], 0FFh ; user or system space ? 22225 00004726 7529 <1> jne short clk_2 ; system space (sysflg <> 0FFh) 22226 00004728 803D[F56C0000]01 <1> cmp byte [u.uno], 1 ; /etc/init ? 22227 0000472F 761A <1> jna short clk_1 ; yes, do not swap out 22228 00004731 66833D[F06C0000]00 <1> cmp word [u.intr], 0 22229 00004739 7616 <1> jna short clk_2 22230 <1> clk_0: 22231 <1> ; 14/10/2015 22232 0000473B FE05[986C0000] <1> inc byte [sysflg] ; Now, we are in system space 22233 00004741 58 <1> pop eax ; return address to the timer interrupt 22234 <1> ; 22235 00004742 B020 <1> MOV AL,EOI ; GET END OF INTERRUPT MASK 22236 <1> ;CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 22237 00004744 E620 <1> OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 22238 <1> ; 22239 00004746 E99FEAFFFF <1> jmp sysrelease ; 'sys release' by clock/timer 22240 <1> clk_1: 22241 0000474B FE0D[EC6C0000] <1> dec byte [u.quant] 22242 <1> clk_2: 22243 00004751 C3 <1> retn ; return to (hardware) timer interrupt routine 22244 <1> 22245 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22246 <1> 22247 <1> ;mov $uquant,r0 / decrement user time quantum 22248 <1> ;decb (r0) 22249 <1> ;bge 1f / if less than 0 22250 <1> ;clrb (r0) / make it 0 22251 <1> ;1: / decrement time out counts return now if priority was not 0 22252 <1> ;cmp 4(sp),$200 / ps greater than or equal to 200 22253 <1> ;bge 2f / yes, check time outs 22254 <1> ;tstb (r0) / no, user timed out? 22255 <1> ;bne 1f / no 22256 <1> ;cmpb sysflg,$-1 / yes, are we outside the system? 22257 <1> ;bne 1f / no, 1f 22258 <1> ;mov (sp)+,r0 / yes, put users r0 in r0 22259 <1> ;sys 0 / sysrele 22260 <1> ;rti 22261 <1> ;2: / priority is high so just decrement time out counts 22262 <1> ;mov $toutt,r0 / r0 points to beginning of time out table 22263 <1> ;2: 22264 <1> ;tstb (r0) / is the time out? 22265 <1> ;beq 3f / yes, 3f (get next entry) 22266 <1> ;decb (r0) / no, decrement the time 22267 <1> ;bne 3f / isit zero now? 22268 <1> ;incb (r0) / yes, increment the time 22269 <1> ;3: 22270 <1> ;inc r0 / next entry 22271 <1> ;cmp r0,$touts / end of toutt table? 22272 <1> ;blo 2b / no, check this entry 22273 <1> ;mov (sp)+,r0 / yes, restore r0 22274 <1> ;rti / return from interrupt 22275 <1> ;1: / decrement time out counts; if 0 call subroutine 22276 <1> ;mov (sp)+,r0 / restore r0 22277 <1> ;mov $240,*$ps / set processor priority to 5 22278 <1> ;jsr r0,setisp / save registers 22279 <1> ;mov $touts-toutt-1,r0 / set up r0 as index to decrement thru 22280 <1> ; / the table 22281 <1> ;1: 22282 <1> ;tstb toutt(r0) / is the time out for this entry 22283 <1> ;beq 2f / yes 22284 <1> ;decb toutt(r0) / no, decrement the time 22285 <1> ;bne 2f / is the time 0, now 22286 <1> ;asl r0 / yes, 2 x r0 to get word index for tout entry 22287 <1> ;jsr r0,*touts(r0) / go to appropriate routine specified in this 22288 <1> ;asr r0 / touts entry; set r0 back to toutt index 22289 <1> ;2: 22290 <1> ;dec r0 / set up r0 for next entry 22291 <1> ;bge 1b / finished? , no, go back 22292 <1> ;br retisp / yes, restore registers and do a rti 22293 <1> 22294 <1> ;retisp: 22295 <1> ;mov (sp)+,clockp / pop values before interrupt off the stack 22296 <1> ;mov (sp)+,r3 22297 <1> ;mov (sp)+,r2 22298 <1> ;mov (sp)+,r1 22299 <1> ;mov (sp)+,r0 22300 <1> ;rti / return from interrupt 22301 <1> 22302 <1> 22303 <1> wakeup: ; / wakeup processes waiting for an event 22304 <1> ; / by linking them to the queue 22305 <1> ; 22306 <1> ; 27/02/2022 22307 <1> ; 15/09/2015 22308 <1> ; 29/06/2015 22309 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 22310 <1> ; 22311 <1> ; 15/05/2013 - 02/06/2014 22312 <1> ; Retro UNIX 8086 v1 modification ! 22313 <1> ; (Process/task switching routine by using 22314 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.) 22315 <1> ; 22316 <1> ; In original UNIX v1, 'wakeup' is called to wake the process 22317 <1> ; sleeping in the specified wait channel by creating a link 22318 <1> ; to it from the last user process on the run queue. 22319 <1> ; If there is no process to wake up, nothing happens. 22320 <1> ; 22321 <1> ; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set 22322 <1> ; 'switching' status of the current process (owns current tty) 22323 <1> ; (via alt + function keys) to a process which has highest 22324 <1> ; priority (on run queue) on the requested tty (0 to 7, except 22325 <1> ; 8 and 9 which are tty identifiers of COM1, COM2 serial ports) 22326 <1> ; as it's console tty. (NOTE: 'p.ttyc' is used to set console 22327 <1> ; tty for tty switching by keyboard.) 22328 <1> ; 22329 <1> ; INPUT -> 22330 <1> ; AL = wait channel (r3) ('tty number' for now) 22331 <1> ; ;;EBX = Run queue (r2) offset 22332 <1> ; 22333 <1> ; ((modified registers: EAX, EBX)) 22334 <1> ; 22335 00004752 0FB6D8 <1> movzx ebx, al ; 29/06/2015 22336 00004755 81C3[C8670000] <1> add ebx, wlist 22337 0000475B 8A03 <1> mov al, [ebx] ; waiting list (waiting process number) 22338 0000475D 20C0 <1> and al, al 22339 0000475F 741E <1> jz short wa0 ; nothing to wakeup 22340 <1> ; 22341 00004761 30E4 <1> xor ah, ah 22342 00004763 8825[EC6C0000] <1> mov [u.quant], ah ; 0 ; time quantum = 0 22343 00004769 8823 <1> mov [ebx], ah ; 0 ; zero wait channel entry 22344 <1> ; 15/09/2015 22345 0000476B 0FB6D8 <1> movzx ebx, al 22346 <1> ; 27/02/2022 (p.waitc is not used) 22347 <1> ;mov [ebx+p.waitc-1], ah ; 0 22348 0000476E FEC4 <1> inc ah 22349 00004770 88A3[C3680000] <1> mov byte [ebx+p.stat-1], ah ; 1 ; SRUN 22350 <1> ; 22351 00004776 57 <1> push edi 22352 00004777 52 <1> push edx 22353 00004778 E851FFFFFF <1> call putlu 22354 0000477D 5A <1> pop edx 22355 0000477E 5F <1> pop edi 22356 <1> wa0: 22357 0000477F C3 <1> retn 22358 <1> 22359 <1> ; 27/02/2022 22360 <1> ; 05/12/2021 22361 <1> ; 30/11/2021 - Retro UNIX 386 v1.2 22362 <1> sleep: 22363 <1> ; 15/09/2015 22364 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 22365 <1> ; 22366 <1> ; 09/05/2013 - 20/03/2014 22367 <1> ; 22368 <1> ; Retro UNIX 8086 v1 modification ! 22369 <1> ; (Process/task switching and quit routine by using 22370 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 22371 <1> ; 22372 <1> ; In original UNIX v1, 'sleep' is called to wait for 22373 <1> ; tty and tape output or input becomes available 22374 <1> ; and process is put on waiting channel and swapped out, 22375 <1> ; then -when the tty or tape is ready to write or read- 22376 <1> ; 'wakeup' gets process back to active swapped-in status.) 22377 <1> ; 22378 <1> ; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and 22379 <1> ; Int 09h keyboard interrupt will set 'quit' or 'switching' 22380 <1> ; status of the current process also INT 1Ch will count down 22381 <1> ; 'uquant' value and INT 09h will redirect scancode of keystroke 22382 <1> ; to tty buffer of the current process and kernel will get 22383 <1> ; user input by using tty buffer of the current process 22384 <1> ; (instead of standard INT 16h interrupt). 22385 <1> ; TTY output will be redirected to related video page of text mode 22386 <1> ; (INT 10h will be called with different video page depending 22387 <1> ; on tty assignment of the active process: 0 to 7 for 22388 <1> ; pseudo screens.) 22389 <1> ; 22390 <1> ; In Retro UNIX 8086 v1, 'sleep' will be called to wait for 22391 <1> ; a keystroke from keyboard or wait for reading or writing 22392 <1> ; characters/data on serial port(s). 22393 <1> ; 22394 <1> ; Character/Terminal input/output through COM1 and COM2 will be 22395 <1> ; performed by related routines in addition to pseudo TTY routines. 22396 <1> ; 22397 <1> ; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013) 22398 <1> ; 22399 <1> ;; 05/10/2013 22400 <1> ;10/12/2013 22401 <1> ;cmp byte [u.uno], 1 22402 <1> ;ja short sleep0 22403 <1> ;retn 22404 <1> 22405 <1> ; 20/03/2014 22406 <1> ;mov bx, [runq] 22407 <1> ;cmp bl, bh 22408 <1> ;jne short sleep0 22409 <1> ; 25/02/2014 22410 <1> ;cmp word ptr [runq], 0 22411 <1> ;ja short sleep0 22412 <1> ;retn 22413 <1> sleep0: 22414 <1> ; 22415 00004780 E849000000 <1> call isintr 22416 <1> ;jnz sysret 22417 <1> ; / wait for event 22418 <1> ; jsr r0,isintr / check to see if interrupt 22419 <1> ; / or quit from user 22420 <1> ; br 2f / something happened 22421 <1> ; / yes, his interrupt so return 22422 <1> ; / to user 22423 <1> ; 05/12/2021 22424 00004785 7405 <1> jz short sleep_2 22425 <1> sleep_3: 22426 00004787 E9F9E9FFFF <1> jmp sysret 22427 <1> sleep_2: 22428 <1> ; 30/06/2015 22429 0000478C 0FB6DC <1> movzx ebx, ah ; 30/06/2015 22430 0000478F 81C3[C8670000] <1> add ebx, wlist 22431 00004795 8A03 <1> mov al, [ebx] 22432 00004797 20C0 <1> and al, al 22433 00004799 7407 <1> jz short sleep1 22434 0000479B 53 <1> push ebx 22435 0000479C E82DFFFFFF <1> call putlu 22436 000047A1 5B <1> pop ebx 22437 <1> sleep1: 22438 000047A2 A0[F56C0000] <1> mov al, [u.uno] 22439 000047A7 8803 <1> mov [ebx], al ; put the process number 22440 <1> ; in the wait channel 22441 <1> ; mov (r0)+,r1 / put number of wait channel in r1 22442 <1> ; movb wlist(r1),-(sp) / put old process number in there, 22443 <1> ; / on the stack 22444 <1> ; movb u.uno,wlist(r1) / put process number of process 22445 <1> ; / to put to sleep in there 22446 <1> ; 30/11/2021 22447 000047A9 31DB <1> xor ebx, ebx 22448 000047AB 8A1D[816C0000] <1> mov bl, [cdev] 22449 000047B1 53 <1> push ebx 22450 <1> ; 15/09/2015 22451 <1> ;movzx ebx, al 22452 000047B2 88C3 <1> mov bl, al 22453 000047B4 C683[C3680000]04 <1> mov byte [ebx+p.stat-1], 4 ; SSLEEP 22454 <1> ; 27/02/2022 (p.waitc is not used) 22455 <1> ;inc ah 22456 <1> ;mov [ebx+p.waitc-1], ah ; wait channel + 1 22457 <1> ; 22458 <1> ; 22459 <1> ;push word [cdev] 22460 <1> ; ; mov cdev,-(sp) / nothing happened in isintr so 22461 000047BB E841FEFFFF <1> call swap 22462 <1> ; jsr r0,swap / swap out process that needs to sleep 22463 <1> ;pop word [cdev] 22464 <1> ; ; mov (sp)+,cdev / restore device 22465 <1> ; 30/11/2021 22466 000047C0 58 <1> pop eax 22467 000047C1 A2[816C0000] <1> mov [cdev], al 22468 000047C6 E803000000 <1> call isintr 22469 <1> ; 22/09/2013 22470 <1> ;jnz sysret 22471 <1> ; jsr r0,isintr / check for interrupt of new process 22472 <1> ; br 2f / yes, return to new user 22473 <1> ; movb (sp)+,r1 / no, r1 = old process number that was 22474 <1> ; / originally on the wait channel 22475 <1> ; beq 1f / if 0 branch 22476 <1> ; mov $runq+4,r2 / r2 points to lowest priority queue 22477 <1> ; mov $300,*$ps / processor priority = 6 22478 <1> ; jsr r0,putlu / create link to old process number 22479 <1> ; clr *$ps / clear the status; process priority = 0 22480 <1> ; 05/12/2021 22481 000047CB 75BA <1> jnz short sleep_3 ; jump to sysret 22482 <1> ;1: 22483 000047CD C3 <1> retn 22484 <1> ; rts r0 / return 22485 <1> ;2: 22486 <1> ;;jmp sysret 22487 <1> ; jmp sysret / return to user 22488 <1> 22489 <1> isintr: 22490 <1> ; 30/11/2021 22491 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 22492 <1> ; 22493 <1> ; 09/05/2013 - 30/05/2014 22494 <1> ; 22495 <1> ; Retro UNIX 8086 v1 modification ! 22496 <1> ; (Process/task switching and quit routine by using 22497 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 22498 <1> ; 22499 <1> ; Retro UNIX 8086 v1 modification: 22500 <1> ; 'isintr' checks if user interrupt request is enabled 22501 <1> ; and there is a 'quit' request by user; 22502 <1> ; otherwise, 'isintr' will return with zf=1 that means 22503 <1> ; "nothing to do". (20/10/2013) 22504 <1> ; 22505 <1> ; 20/10/2013 22506 000047CE 66833D[DA6C0000]00 <1> cmp word [u.ttyp], 0 ; has process got a tty ? 22507 000047D6 761F <1> jna short isintr2 ; retn 22508 <1> ; 03/09/2013 22509 <1> ; (nothing to do) 22510 <1> ;retn 22511 <1> ; 22/09/2013 22512 000047D8 66833D[F06C0000]00 <1> cmp word [u.intr], 0 22513 000047E0 7615 <1> jna short isintr2 ; retn 22514 <1> ; 30/05/2014 22515 <1> ;push ax 22516 000047E2 50 <1> push eax ; 30/11/2021 22517 000047E3 66A1[F26C0000] <1> mov ax, [u.quit] 22518 000047E9 6609C0 <1> or ax, ax ; 0 ? 22519 000047EC 7408 <1> jz short isintr1 ; zf = 1 22520 000047EE 6683F8FE <1> cmp ax, 0FFFEh ; 'ctrl + brk' check 22521 000047F2 7702 <1> ja short isintr1 ; 0FFFFh, zf = 0 22522 <1> ;xor ax, ax ; zf = 1 22523 <1> ; 30/11/2021 22524 000047F4 31C0 <1> xor eax, eax 22525 <1> isintr1: 22526 <1> ;pop ax 22527 <1> ; 30/11/2021 22528 000047F6 58 <1> pop eax 22529 <1> isintr2: ; 22/09/2013 22530 <1> ; zf=1 -> nothing to do 22531 000047F7 C3 <1> retn 22532 <1> 22533 <1> ; UNIX v1 original 'isintr' routine... 22534 <1> ;mov r1,-(sp) / put number of wait channel on the stack 22535 <1> ;mov r2,-(sp) / save r2 22536 <1> ;mov u.ttyp,r1 / r1 = pointer to buffer of process control 22537 <1> ; / typewriter 22538 <1> ;beq 1f / if 0, do nothing except skip return 22539 <1> ;movb 6(r1),r1 / put interrupt char in the tty buffer in r1 22540 <1> ;beq 1f / if its 0 do nothing except skip return 22541 <1> ;cmp r1,$177 / is interrupt char = delete? 22542 <1> ;bne 3f / no, so it must be a quit (fs) 22543 <1> ;tst u.intr / yes, value of u.intr determines handling 22544 <1> ; / of interrupts 22545 <1> ;bne 2f / if not 0, 2f. If zero do nothing. 22546 <1> ;1: 22547 <1> ;tst (r0)+ / bump r0 past system return (skip) 22548 <1> ;4: 22549 <1> ;mov (sp)+,r2 / restore r1 and r2 22550 <1> ;mov (sp)+,r1 22551 <1> ;rts r0 22552 <1> ;3: / interrupt char = quit (fs) 22553 <1> ;tst u.quit / value of u.quit determines handling of quits 22554 <1> ;beq 1b / u.quit = 0 means do nothing 22555 <1> ;2: / get here because either u.intr <> 0 or u.qult <> O 22556 <1> ;mov $tty+6,r1 / move pointer to tty block into r1 22557 <1> ;1: / find process control tty entry in tty block 22558 <1> ;cmp (r1),u.ttyp / is this the process control tty buffer? 22559 <1> ;beq 1f / block found go to 1f 22560 <1> ;add $8,r1 / look at next tty block 22561 <1> ;cmp r1,$tty+[ntty*8]+6 / are we at end of tty blocks 22562 <1> ;blo 1b / no 22563 <1> ;br 4b / no process control tty found so go to 4b 22564 <1> ;1: 22565 <1> ;mov $240,*$ps / set processor priority to 5 22566 <1> ;movb -3(r1),0f / load getc call argument; character llst 22567 <1> ; / identifier 22568 <1> ;inc 0f / increment 22569 <1> ;1: 22570 <1> ;jsr r0,getc; 0:.. / erase output char list for control 22571 <1> ; br 4b / process tty. This prevents a line of stuff 22572 <1> ; / being typed out after you hit the interrupt 22573 <1> ; / key 22574 <1> ;br 1b 22575 %include 'u5.s' ; 03/06/2015 22576 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 22577 <1> ; (re-write kernel for test by using previous version without a major defect) 22578 <1> ; **************************************************************************** 22579 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC 22580 <1> ; Last Modification: 17/07/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.3) 22581 <1> ; ---------------------------------------------------------------------------- 22582 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 22583 <1> ; (v0.1 - Beginning: 11/07/2012) 22584 <1> ; 22585 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 22586 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 22587 <1> ; 22588 <1> ; 22589 <1> ; 22590 <1> ; Retro UNIX 8086 v1 - U5.AS M (07/08/2013) //// UNIX v1 -> u5.s 22591 <1> ; 22592 <1> ; **************************************************************************** 22593 <1> 22594 <1> ; 09/03/2022 22595 <1> ; 09/01/2022 22596 <1> ; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification 22597 <1> mget_w: 22598 <1> ; 28/10/2021 22599 <1> ; 22/08/2021 22600 <1> ; 20/08/2021 22601 <1> ; 25/05/2020 22602 <1> ; 24/05/2020 - Retro UNIX 386 v2 22603 000047F8 C605[3A6D0000]01 <1> mov byte [mget_rw], 1 ; write access 22604 000047FF EB07 <1> jmp short mget 22605 <1> mget_r: 22606 <1> ; 28/10/2021 22607 <1> ; 22/08/2021 22608 <1> ; 25/05/2020 22609 <1> ; 24/05/2020 - Retro UNIX 386 v2 22610 00004801 C605[3A6D0000]00 <1> mov byte [mget_rw], 0 ; read access 22611 <1> mget: 22612 <1> ; 17/07/2022 22613 <1> ; 09/03/2022 22614 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 22615 <1> ; 28/11/2021 22616 <1> ; 22/11/2021 22617 <1> ; 28/10/2021 - temporary (simplified code) 22618 <1> ; 22/08/2021 22619 <1> ; 20/08/2021 22620 <1> ; 25/05/2020 22621 <1> ; 24/05/2020 22622 <1> ; 05/05/2020 22623 <1> ; 02/05/2020, 03/05/2020 22624 <1> ; 29/04/2020 - Retro UNIX 386 v2 22625 <1> ; New inode model/format (Modified UNIX v7 inode model) 22626 <1> ; 22627 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 22628 <1> ; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 22629 <1> ; 22630 <1> ; Get existing or (allocate) a new disk block for file 22631 <1> ; 22632 <1> ; INPUTS -> 22633 <1> ; u.fofp (file offset pointer) 22634 <1> ; inode 22635 <1> ; u.off (file offset) 22636 <1> ; OUTPUTS -> 22637 <1> ; r1 (physical block number) 22638 <1> ; r2, r3, r5 (internal) 22639 <1> ; 22640 <1> ; ((AX = R1)) output 22641 <1> ; (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM) 22642 <1> ; 22643 <1> ; Modified registers: eax, edx, ebx, ecx, esi, edi, ebp 22644 <1> 22645 <1> ; Retro UNIX 386 v2 'mget' procedure 22646 <1> ; source code reference: 22647 <1> ; 'mget' procedure in UNIXHDCP.ASM (25/01/2020) by Erdogan Tan 22648 <1> 22649 <1> ; Get sector/block address for current file pointer 22650 <1> ; (If file pointer points to a number greater than current file 22651 <1> ; size, a new -empty- sector/block will be created/written.) 22652 <1> 22653 <1> ; Note: 'mget' procedure will be used for only RUNIX v2 FS. 22654 <1> ; (installable file system drivers will not use 'mget') 22655 <1> ; !!! 512 bytes per sector !!! ; 02/05/2020 22656 <1> 22657 <1> ; ! 64 bit fofp ! but Retro UNIX 386 v2 kernel will use 32 bit 22658 <1> ; file offset for regular files and directories. 22659 <1> ; ('mget' procedure will be called for regular files & directories) 22660 <1> 22661 <1> ; 28/10/2021 22662 <1> ; Note: 'mget' uses only current inode ([ii], 'inode:') 22663 <1> ; (inode must be loaded at 'inode:' addr by 'iget' before 'mget') 22664 <1> 22665 <1> ; mov *u.fofp,mq / file offset in mq 22666 <1> ; clr ac / later to be high sig 22667 <1> ; mov $-8,lsh / divide ac/mq by 256. 22668 <1> ; mov mq,r2 22669 <1> ; bit $10000,i.flgs / lg/sm is this a large or small file 22670 <1> ; bne 4f / branch for large file 22671 <1> 22672 <1> ; 09/01/2022 22673 <1> ; Return: eax = physical block/sector number 22674 <1> mget_0: 22675 00004808 8B35[B86C0000] <1> mov esi, [u.fofp] 22676 0000480E 8B1E <1> mov ebx, [esi] 22677 <1> ; ebx = file offset 22678 <1> 22679 <1> ; 20/08/2021 22680 00004810 C1EB09 <1> shr ebx, 9 ; / 512 (to convert byte offset to sector offset) 22681 <1> 22682 00004813 F605[25680000]10 <1> test byte [i.flgs+1], 10h ; is this a large or small file addr? 22683 0000481A 7405 <1> jz short mget_1 ; small file addressing 22684 0000481C E984000000 <1> jmp mget_5 ; large file addressing 22685 <1> mget_1: 22686 <1> ; If large file flag is clear -not set- RUNIX v2 FS inode 22687 <1> ; will contain 10 direct disk block/sector dword pointers. 22688 <1> 22689 <1> ; 05/05/2020 22690 <1> ;shr ebx, 9 ; / 512 (to convert byte offset to sector offset) 22691 <1> 22692 00004821 83FB0A <1> cmp ebx, 10 ; block 10 22693 00004824 7338 <1> jnb short mget_3 ; file offset >= 5120 22694 <1> 22695 <1> ; 05/05/2020 22696 <1> ;cmp ebx, 5120 22697 <1> ;jnb short mget_3 ; file offset >= 5120 22698 <1> 22699 <1> ;mov bl, bh 22700 <1> ;and bl, 1Eh ; clear all bits but bits 1,2,3,4 ; 0,2,..,18 22701 <1> ; ; max. value = 12h = 10010b = 18 (because ebx <= 5119) 22702 <1> ;shl bl, 1 ; * 2 ; max. value = 24h = 100100b = 36 22703 <1> ;xor bh, bh ; clear bh 22704 <1> ; RUNIX v2 (RUFS 2) file system bytes per sector value 22705 <1> ; is always 512. 22706 <1> ; ebx = 4*(ebx/512) = 0 to 36 22707 <1> 22708 <1> ; 05/05/2020 22709 00004826 C0E302 <1> shl bl, 2 ; * 4 22710 <1> ; ebx = 0 to 36 22711 <1> 22712 00004829 8B83[30680000] <1> mov eax, [ebx+i.dskp] ; disk sector addr ptr 0 to 9 for file 22713 <1> ; 22/08/2021 22714 0000482F 89DE <1> mov esi, ebx 22715 <1> ;xor ebx, ebx ; 0 22716 <1> ; 09/03/2022 22717 <1> ;; 09/01/2022 22718 <1> ;xor bl, bl 22719 <1> 22720 00004831 09C0 <1> or eax, eax 22721 00004833 7512 <1> jnz short mget_2 ; existing block/sector (logical) 22722 <1> 22723 00004835 56 <1> push esi ; * ; 22/08/2021 22724 00004836 E872010000 <1> call alloc_m ; 24/05/2020 22725 <1> ;call alloc ; allocate a new sector/block for this file 22726 <1> ; eax = sector/block number 22727 <1> ; ebx = buffer header address 22728 0000483B 5E <1> pop esi ; * ; 22/08/2021 22729 <1> ; 28/11/2021 22730 <1> ;jc short mget_2 22731 <1> ; cf = 1 -> eax = 'no free block' error 22732 <1> ; 22/08/2021 22733 0000483C 8986[30680000] <1> mov [esi+i.dskp], eax ; logical sector/block address 22734 <1> 22735 <1> ; 09/01/2022 22736 00004842 E8BF040000 <1> call setimod ; set inode modification flag 22737 <1> ; and set modification time 22738 <1> 22739 <1> ; eax = logical sector/block number 22740 <1> ; ([idev] = logical drive number) 22741 <1> ; 28/10/2021 22742 <1> ; [cdev] = logical drive number (0 or 1) 22743 <1> ; (0 = root fs, 1 = mounted fs) 22744 <1> mget_2: 22745 <1> ; 09/01/2022 22746 <1> ; eax = logical sector/block number 22747 00004847 F605[816C0000]01 <1> test byte [cdev], 1 22748 0000484E 7507 <1> jnz short mget_14 22749 <1> ; convert to physical sector/block number 22750 00004850 0305[586D0000] <1> add eax, [systm+SB.BootSectAddr] 22751 00004856 C3 <1> retn 22752 <1> ; 09/01/2022 22753 <1> mget_14: 22754 <1> ; convert to physical sector/block number 22755 00004857 0305[606F0000] <1> add eax, [mount+SB.BootSectAddr] 22756 0000485D C3 <1> retn 22757 <1> 22758 <1> ; rts r0 22759 <1> mget_3: ; 3: / adding on block which changes small file to a large file 22760 <1> ; 22/11/2021 22761 0000485E E84A010000 <1> call alloc_m ; 24/05/2020 22762 <1> ;call alloc ; allocate a new sector/block for this file 22763 <1> ; eax = sector/block number 22764 <1> ; ebx = buffer header ; 24/05/2020 22765 <1> ; 28/11/2021 22766 <1> ;jc short mget_2 ; error code in eax 22767 <1> 22768 <1> ; 09/01/2022 22769 <1> ; convert to physical block/sector number 22770 00004863 50 <1> push eax ; *!* ; logical sector/block number 22771 00004864 E8DEFFFFFF <1> call mget_2 22772 <1> 22773 <1> ; EAX (r1) = Physical block (sector) number 22774 00004869 E886110000 <1> call wslot 22775 <1> ; jsr r0,wslot / set up I/O buffer for write, r5 points to 22776 <1> ; / first data word in buffer 22777 <1> ; EAX (r1) = Physical block number 22778 <1> ; 28/11/2021 22779 <1> ; ebx = buffer (data) address 22780 <1> ; 22/11/2021 22781 0000486E 31C9 <1> xor ecx, ecx 22782 00004870 B10A <1> mov cl, 10 ; r3, transfer old physical block pointers 22783 <1> ; into new indirect block area for the new 22784 <1> ; large file 22785 00004872 89DF <1> mov edi, ebx ; r5 22786 00004874 BE[30680000] <1> mov esi, i.dskp ; current inode's direct disk addr ptrs 22787 00004879 89C2 <1> mov edx, eax 22788 0000487B 31C0 <1> xor eax, eax 22789 <1> mget_4: 22790 0000487D A5 <1> movsd 22791 0000487E 8946FC <1> mov [esi-4], eax ; 0 22792 00004881 E2FA <1> loop mget_4 22793 <1> 22794 <1> ; 22/11/2021 22795 00004883 B176 <1> mov cl, 128-10 ; clear rest of data buffer 22796 <1> ;mget_4: ; 1 22797 00004885 F3AB <1> rep stosd 22798 <1> ; clr (r5)+ 22799 <1> ; dec r3 22800 <1> ; bgt 1b 22801 00004887 89D0 <1> mov eax, edx 22802 <1> ; EAX (r1) = Physical block number 22803 00004889 E873110000 <1> call dskwr 22804 <1> ; jsr r0,dskwr / write new indirect block on disk 22805 <1> 22806 <1> ;; EAX (r1) = Physical block number 22807 <1> 22808 <1> ; 09/01/2022 22809 0000488E 8F05[30680000] <1> pop dword [i.dskp] ; *!* ; logical sector/block number 22810 <1> 22811 <1> ; eax = logical disk sector/block number/addr ; 09/01/2022 22812 <1> ;mov [i.dskp], eax ; 22/11/2021 22813 <1> ; mov r1,i.dskp / put pointer to indirect block in i-node 22814 <1> 22815 00004894 800D[25680000]10 <1> or byte [i.flgs+1], 10000b ; 10h ; 16 ; large file flag 22816 <1> ; bis $10000,i.flgs / set large file bit 22817 <1> ; / in i.flgs word of i-node 22818 0000489B E866040000 <1> call setimod 22819 <1> ; jsr r0,setimod / set i-node modified flag 22820 <1> 22821 000048A0 E963FFFFFF <1> jmp mget_0 ; 09/01/2022 22822 <1> ; br mget 22823 <1> 22824 <1> mget_5: ; 4 ; large file 22825 <1> ; 13/11/2019 (UNIXHDCP.ASM) 22826 <1> ; 22827 <1> ; Retro UNIX 386 v2 disk inode contains.. 22828 <1> ; (if large file flag is set) 22829 <1> ; 8 indirect disk block/sector dword pointers 22830 <1> ; +1 double indirect disk block/sector dword pointers 22831 <1> ; +1 triple indirect disk block/sector dword pointers 22832 <1> 22833 <1> ; check indirect pointers limit (as file offset) 22834 <1> ; 8*128 = 1024 blocks (or sectors) or 512 KB 22835 <1> ; check dx (file offset hw) value 22836 <1> 22837 <1> ; 03/05/2020 22838 <1> ;cmp ebx, 524288 ; is file offset >= 524288 ? 22839 <1> ;jnb short mget_6 ; yes, check double indirect limit 22840 <1> 22841 <1> ; 05/05/2020 22842 000048A5 81FB00040000 <1> cmp ebx, 1024 ; block 1024 (byte 524288) 22843 000048AB 7320 <1> jnb short mget_6 ; check double indirect limit 22844 <1> 22845 000048AD C605[3C6D0000]01 <1> mov byte [level], 1 ; levels, 1 = indirect blocks 22846 <1> 22847 <1> ; 05/05/2020 22848 <1> ;shr ebx, 9 ; ebx = sector offset (flat) 22849 <1> 22850 000048B4 88D9 <1> mov cl, bl 22851 000048B6 80E17F <1> and cl, 127 22852 000048B9 880D[3D6D0000] <1> mov [level+1], cl ; level 1, direct block ptr index (0 to 127) 22853 <1> ;shr bx, 7 ; bl = level 0, indirect block pointer index (0 to 7) 22854 <1> ; 17/07/2022 22855 000048BF C1EB07 <1> shr ebx, 7 22856 <1> ;mov [level+2], bl 22857 <1> 22858 000048C2 C0E302 <1> shl bl, 2 ; * 4 to convert index number to offset 22859 <1> 22860 <1> ;mov esi, i.dskp 22861 <1> ;add esi, ebx 22862 <1> 22863 000048C5 8DB3[30680000] <1> lea esi, [ebx+i.dskp] 22864 <1> 22865 000048CB EB64 <1> jmp short mget_8 22866 <1> 22867 <1> mget_6: 22868 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 22869 <1> ; 03/05/2020 22870 <1> ; 13/11/2019 (UNIXHDCP.ASM) 22871 <1> ; check double indirect pointer limit (as file offset) 22872 <1> ; (128*128)+1024 = 16384+1024 blocks or 8 MB + 512 KB 22873 <1> ; check dx (file offset hw) value 22874 <1> 22875 <1> ;cmp ebx, 8912896 ; >= 17408 sectors (16384+1024) ? 22876 <1> ;jnb short mget_7 ; yes, use triple indirect pointer (block) 22877 <1> 22878 <1> ; 05/05/2020 22879 000048CD 81FB00440000 <1> cmp ebx, 17408 ; block 17408 (byte 8912896) 22880 000048D3 7328 <1> jnb short mget_7 ; use triple indirect pointer (block) 22881 <1> 22882 000048D5 C605[3C6D0000]02 <1> mov byte [level], 2 ; levels, 2 = double indirect blocks 22883 <1> 22884 <1> ;sub ebx, 524288 ; 1024 sectors 22885 <1> ;shr ebx, 9 ; ebx = sector offset (flat) 22886 <1> ; (from sector 1024) 22887 <1> ; 05/05/2020 22888 000048DC 81EB00040000 <1> sub ebx, 1024 ; offset from sector 1024 22889 <1> 22890 000048E2 88D9 <1> mov cl, bl 22891 000048E4 80E17F <1> and cl, 127 22892 000048E7 880D[3D6D0000] <1> mov [level+1], cl 22893 <1> ; level 2, direct block ptr index (0 to 127) 22894 <1> ;shr bx, 7 22895 <1> ; 17/07/2022 22896 000048ED C1EB07 <1> shr ebx, 7 22897 000048F0 881D[3E6D0000] <1> mov [level+2], bl 22898 <1> ; level 1, indirect block ptr index (0 to 127) 22899 <1> 22900 000048F6 BE[50680000] <1> mov esi, i.dskp + 32 ; 8*4 22901 <1> ; level 0, double indirect block pointer 22902 000048FB EB34 <1> jmp short mget_8 22903 <1> 22904 <1> mget_7: 22905 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 22906 <1> ; 03/05/2020 22907 <1> ; 13/11/2019 (UNIXHDCP.ASM) 22908 <1> ; triple indirect pointer ; 8912896 to 1082654720 bytes 22909 <1> ;mov esi, i.dskp + 36 ; 9*4 22910 <1> 22911 000048FD C605[3C6D0000]03 <1> mov byte [level], 3 ; levels, 3 = triple indirect blocks 22912 <1> 22913 <1> ;sub ebx, 8912896 ; 17408 sectors (16384+1024) 22914 <1> ;shr ebx, 9 ; ebx = sector offset (flat) 22915 <1> ; (from sector 17408) 22916 <1> ; 05/05/2020 22917 00004904 81EB00440000 <1> sub ebx, 17408 ; offset from sector 17408 22918 <1> 22919 0000490A 88D9 <1> mov cl, bl 22920 0000490C 80E17F <1> and cl, 127 22921 0000490F 880D[3D6D0000] <1> mov [level+1], cl 22922 <1> ; level 3, direct block ptr index (0 to 127) 22923 00004915 C1EB07 <1> shr ebx, 7 22924 00004918 88D9 <1> mov cl, bl 22925 0000491A 80E17F <1> and cl, 127 22926 0000491D 880D[3E6D0000] <1> mov [level+2], cl 22927 <1> ; level 2, indirect block ptr index (0 to 127) 22928 <1> ;shr bx, 7 22929 <1> ; 17/07/2022 22930 00004923 C1EB07 <1> shr ebx, 7 22931 00004926 881D[3F6D0000] <1> mov [level+3], bl 22932 <1> ; level 1, double indir blk ptr index (0 to 127) 22933 <1> 22934 0000492C BE[54680000] <1> mov esi, i.dskp + 36 ; 9*4 22935 <1> ; level 0, triple indirect block pointer 22936 <1> mget_8: 22937 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 22938 00004931 8B06 <1> mov eax, [esi] 22939 00004933 09C0 <1> or eax, eax ; R1 22940 00004935 751A <1> jnz short mget_10 ; 2f 22941 <1> ; bne 2f / if no indirect block exists 22942 00004937 56 <1> push esi ; * ; 24/05/2020 22943 <1> 22944 00004938 E870000000 <1> call alloc_m ; 24/05/2020 22945 <1> ;call alloc ; allocate a new block for this file 22946 <1> ; eax = block number 22947 <1> ; ebx = buffer header address 22948 <1> ; [pdn] = physical drive number ; 25/05/2020 22949 <1> ;jc mget_2 ; cf -> 1 & eax = 0 -> no free block 22950 <1> 22951 0000493D 5E <1> pop esi ; * ; 24/05/2020 22952 <1> ;jc short mget_9 22953 <1> 22954 <1> ; 09/01/2022 22955 <1> ; eax = logical sector/block number 22956 <1> 22957 0000493E 8906 <1> mov [esi], eax ; record sector/block address on i.dskp area 22958 <1> 22959 00004940 E8C1030000 <1> call setimod 22960 <1> ; jsr r0,setimod / set i-node modified byte 22961 <1> ; EAX = new block number (logical) 22962 <1> 22963 <1> ; 09/01/2022 22964 <1> ; convert to physical block/sector number 22965 00004945 E8FDFEFFFF <1> call mget_2 22966 <1> ; 22967 0000494A E8AEFDFFFF <1> call clear 22968 <1> ; jsr r0,clear / clear new block 22969 <1> ; 09/03/2022 22970 <1> ;add ebx, 8 22971 <1> ; ebx = buffer data address 22972 <1> ; 22/11/2021 22973 0000494F EB0A <1> jmp short mget_11 22974 <1> ;mget_9: 22975 <1> ; pop edx ; * ; 09/01/2022 22976 <1> ; retn 22977 <1> mget_10: ;2 22978 <1> ; 09/01/2022 22979 <1> ; eax = logical sector/block number/address 22980 <1> ; convert to physical sector/block number/address 22981 00004951 E8F1FEFFFF <1> call mget_2 22982 <1> ; 05/03/2013 22983 <1> ; EAX = r1, physical block number (of indirect block) 22984 00004956 E835100000 <1> call dskrd ; read indirect block 22985 <1> ; jsr r0,dskrd / read in indirect block 22986 <1> ;jc short mget_9 22987 <1> mget_11: 22988 <1> ; 22/11/2021 22989 <1> ; eax = physical block/sector address 22990 <1> ; ebx = buffer (data) address ; 09/03/2022 22991 <1> 22992 0000495B 89C2 <1> mov edx, eax ; * ; save physical sector number in edx 22993 <1> 22994 0000495D 0FB605[3C6D0000] <1> movzx eax, byte [level] 22995 00004964 8A80[3C6D0000] <1> mov al, [eax+level] ; get sector pointer offset 22996 0000496A C1E002 <1> shl eax, 2 ; * 4 ; 09/01/2022 22997 <1> ;shl ax, 2 ; * 4 22998 <1> 22999 0000496D 01C3 <1> add ebx, eax 23000 <1> 23001 0000496F 8B03 <1> mov eax, [ebx] ; put logical block no of block 23002 <1> ; in file sought in R1 (EAX) 23003 <1> ; mov (r2),r1 / put physical block no of block in file 23004 <1> ; / sought in r1 23005 <1> 23006 00004971 21C0 <1> and eax, eax ; if logical sector/block number is zero 23007 <1> ; then we need a new block for file 23008 00004973 740D <1> jz short mget_12 23009 <1> 23010 00004975 FE0D[3C6D0000] <1> dec byte [level] 23011 0000497B 75D4 <1> jnz short mget_10 23012 <1> 23013 <1> ; 09/03/2022 23014 <1> ;sub ebx, ebx ; ebx = 0 ; existing sector 23015 <1> 23016 <1> ;retn 23017 <1> ; 09/01/2022 23018 <1> ; eax = logical block/sector number 23019 0000497D E9C5FEFFFF <1> jmp mget_2 23020 <1> 23021 <1> mget_12: 23022 <1> ; 22/11/2021 23023 00004982 52 <1> push edx ; * 23024 00004983 53 <1> push ebx ; ** ; buffer data position 23025 00004984 E824000000 <1> call alloc_m 23026 <1> ;call alloc ; allocate a new block for this file 23027 <1> ; eax = block number (logical) 23028 <1> ; ebx = buffer header address 23029 00004989 5E <1> pop esi ; ** 23030 <1> ; 09/01/2022 23031 <1> ;pop edx ; * 23032 <1> ;jc short mget_9 ; cf -> 1 & eax = 0 -> no free block 23033 <1> 23034 0000498A 8906 <1> mov [esi], eax ; record/save block number (logical) 23035 <1> 23036 <1> ; 22/11/2021 23037 0000498C 870424 <1> xchg eax, [esp] ; * 23038 <1> 23039 <1> ; eax (r1) = physical block number (of indirect block) 23040 0000498F E860100000 <1> call wslot 23041 <1> ; jsr r0,wslot 23042 <1> ; eax (r1) = physical block number 23043 <1> ; ebx (r5) = pointer to buffer (indirect block) 23044 00004994 E868100000 <1> call dskwr 23045 <1> ; eax = r1 = physical block number (of indirect block) 23046 <1> ; jsr r0,dskwr / write newly modified indirect block 23047 <1> ; / back out on disk 23048 00004999 58 <1> pop eax ; * ; 31/07/2013 23049 <1> ; mov (sp),r1 / restore block number of new block 23050 <1> 23051 <1> ; 09/01/2022 23052 <1> ; eax = logical sector/block number/address of new block 23053 <1> ; convert to physical sector/block number/address 23054 0000499A E8A8FEFFFF <1> call mget_2 23055 <1> 23056 0000499F E859FDFFFF <1> call clear 23057 <1> ; jsr r0,clear / clear new block 23058 <1> 23059 000049A4 FE0D[3C6D0000] <1> dec byte [level] 23060 000049AA 75AF <1> jnz short mget_11 23061 <1> ; ebx = buffer (data) address ; 09/03/2022 23062 <1> 23063 <1> ; 09/01/2022 23064 <1> ; eax = physical sector/block number/address of new block 23065 <1> 23066 <1> ; 22/11/2021 23067 <1> ; ebx = buffer address 23068 <1> mget_13: ; 2 23069 <1> ; eax (r1) = Block number of new block 23070 000049AC C3 <1> retn 23071 <1> ; rts r0 23072 <1> 23073 <1> ; 09/01/2022 23074 <1> ; 26/11/2021 23075 <1> ; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification 23076 <1> alloc_m: 23077 <1> ; 27/11/2021 23078 <1> ; 28/10/2021 23079 <1> ; 07/05/2021 23080 <1> ; 26/05/2020 23081 <1> ; 25/05/2020 23082 <1> ; 24/05/2020 - Retro UNIX 386 v2 23083 <1> ; 'alloc' call in 'mget' 23084 <1> ; 23085 <1> ; (('mget_r' will be returned with error)) 23086 <1> ; (('mget_w' will continue to 'alloc')) 23087 <1> 23088 <1> ; Note: 'sysread' will return with cf = 0, eax = 0 23089 <1> ; if [fofp] >= file size (eax = 0 --> EOF) 23090 <1> ; So, if we are here, that means [fofp] < file size 23091 <1> ; but disk address is 0. 23092 <1> 23093 000049AD 803D[3A6D0000]01 <1> cmp byte [mget_rw], 1 ; write access ? (mget_w) 23094 000049B4 730F <1> jnb short alloc ; yes (this is a call from 'mget_w') 23095 <1> ; ((cf = 1)) 23096 <1> ; no (this is a call from 'mget_r') ! 23097 <1> ;mov eax, ERR_FILE_SIZE ; file size error (inode error!) 23098 <1> ; [User may change this empty/invalid inode (disk) sector 23099 <1> ; pointer with a new valid inode (disk) sector pointer 23100 <1> ; by writing new clear (zero) sector to same file position 23101 <1> ; in order to correct file size -inode parm/content- error. 23102 <1> ; It may be useful for recovering lost data if other sector 23103 <1> ; pointers are not empty.] 23104 <1> ;retn 23105 <1> ; 27/11/2021 23106 000049B6 C705[186D0000]1400- <1> mov dword [u.error], ERR_FILE_SIZE 23107 000049BE 0000 <1> 23108 <1> ; file size error (inode error!) 23109 000049C0 E9A0E7FFFF <1> jmp error 23110 <1> alloc: 23111 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 23112 <1> ; 27/11/2021 23113 <1> ; 26/11/2021 - Major modification for Runix v2 file system 23114 <1> ; (I have called this kernel version as v1.2, it is a 23115 <1> ; debug/test version just before Retro UNIX 386 v2 kernel) 23116 <1> ; ((there were running problems on new version, 23117 <1> ; so i am developing an intermediate version with minimum 23118 <1> ; modification on v1.1 code which is successfuly running)) 23119 <1> ; ; /// Erdogan Tan - Istanbul, 26/11/2021 /// 23120 <1> ; 23121 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 23122 <1> ; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 23123 <1> ; 23124 <1> ; get a free block and 23125 <1> ; set the corresponding bit in the free storage map 23126 <1> ; 23127 <1> ; INPUTS -> 23128 <1> ; cdev (current device) 23129 <1> ; r2 23130 <1> ; r3 23131 <1> ; OUTPUTS -> 23132 <1> ; r1 (physical block number of block assigned) 23133 <1> ; smod, mmod, systm (super block), mount (mountable super block) 23134 <1> ; 23135 <1> ; ((AX = R1)) output 23136 <1> ; (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM) 23137 <1> ; ((Modified registers: edx, ecx)) 23138 <1> 23139 <1> ; 26/11/2021 23140 <1> ; INPUT: 23141 <1> ; [cdev] = current device (root = 0, mounted = 1) 23142 <1> ; OUTPUT: 23143 <1> ; eax = disk block/sector number/address (physical) 23144 <1> ; (ebx = disk buffer address for sector/block in eax) 23145 <1> ; 23146 <1> ; Note: 23147 <1> ; Free blocks map will be modified and written to it's disk. 23148 <1> ; Superblock (buffer) of [cdev] will be modified and it's 23149 <1> ; modification flag will be set; but the superblock 23150 <1> ; will not be written to it's disk in this 'alloc' procedure) 23151 <1> ; 23152 <1> ; Modified registers: eax, ebx, ecx, edx, esi, edi, ebp 23153 <1> 23154 <1> ; 09/01/2022 23155 <1> ; Return: eax = logical block/sector number 23156 <1> 23157 <1> ; 26/11/2021 23158 000049C5 BB[546D0000] <1> mov ebx, systm ; (SuperBlock of root file system) 23159 <1> ; mov $systm,r2 / start of inode and free storage map for drum 23160 000049CA F605[816C0000]01 <1> test byte [cdev], 1 23161 <1> ; tst cdev 23162 000049D1 7405 <1> jz short alloc_1 23163 <1> ; beq 1f / drum is device 23164 000049D3 BB[5C6F0000] <1> mov ebx, mount ; (SuperBlock of mounted file system) 23165 <1> ; mov $mount,r2 / disk or tape is device, start of inode and 23166 <1> ; / free storage map 23167 <1> alloc_1: ; 1 23168 <1> ; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code 23169 000049D8 F6436A01 <1> test byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs 23170 000049DC 7507 <1> jnz short alloc_2 ; 'read only file system' error 23171 <1> ; 23172 000049DE 8B4B38 <1> mov ecx, [ebx+SB.FreeBlocks] ; count of free blocks/sectors 23173 000049E1 21C9 <1> and ecx, ecx 23174 000049E3 750F <1> jnz short alloc_3 23175 <1> alloc_2: 23176 <1> ; 'no free blocks on disk !' error 23177 000049E5 C705[186D0000]2100- <1> mov dword [u.error], ERR_ALLOC 23178 000049ED 0000 <1> 23179 000049EF E971E7FFFF <1> jmp error 23180 <1> alloc_3: 23181 <1> ; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code 23182 000049F4 31C0 <1> xor eax, eax 23183 <1> ; 23/07/2021 23184 000049F6 8B4B3C <1> mov ecx, [ebx+SB.FirstFreeBlk] ; 1st free sector number 23185 <1> ; (as logical sector number) 23186 000049F9 09C9 <1> or ecx, ecx 23187 000049FB 7415 <1> jz short alloc_5 ; 0 = initial/reset value or 'not valid' 23188 000049FD 41 <1> inc ecx ; 0FFFFFFFFh -> 0 23189 000049FE 7412 <1> jz short alloc_5 ; 'not valid' or 'not calculated' 23190 00004A00 49 <1> dec ecx ; restore first free block value 23191 00004A01 89C8 <1> mov eax, ecx 23192 <1> ; 1 allocation byte (in fbm) is for 8 sectors 23193 00004A03 C1E903 <1> shr ecx, 3 ; first free block number / 8 23194 00004A06 80E1FC <1> and cl, ~3 ; dword alignment (to backward) 23195 <1> ; 27/11/2021 23196 00004A09 890D[406D0000] <1> mov [free_map_offset], ecx ; byte position on fbm 23197 <1> alloc_4: 23198 00004A0F C1E80C <1> shr eax, 12 ; 1 fbm sector for 4096 sectors 23199 <1> alloc_5: 23200 <1> ; 26/11/2021 23201 00004A12 53 <1> push ebx ; ** ; superblock buffer address 23202 <1> ; eax = fbm sector index 23203 00004A13 A3[446D0000] <1> mov [free_map_index], eax 23204 00004A18 034318 <1> add eax, [ebx+SB.FreeMapAddr] 23205 <1> ; free blocks map start sector addr 23206 <1> ; 09/01/2022 23207 00004A1B 034304 <1> add eax, [ebx+SB.BootSectAddr] 23208 <1> ; + Hidden Sectors 23209 <1> ; 23210 <1> ; eax = physical sector number 23211 00004A1E E86D0F0000 <1> call dskrd 23212 <1> ; cpu returns here if there is/was not an error in 'dskrd' 23213 <1> ; eax = physical sector number 23214 <1> ; ebx = buffer data address 23215 <1> ; 27/11/2021 23216 00004A23 8B15[406D0000] <1> mov edx, [free_map_offset] ; byte position on fbm 23217 00004A29 A3[486D0000] <1> mov [free_map_sector], eax ; physical sector number 23218 00004A2E B9FF010000 <1> mov ecx, 511 23219 <1> ;and edx, 511 23220 00004A33 21CA <1> and edx, ecx ; fbm byte offset in fbm buffer 23221 00004A35 41 <1> inc ecx ; 512 23222 00004A36 01D9 <1> add ecx, ebx 23223 00004A38 01DA <1> add edx, ebx ; + buffer address 23224 00004A3A 5B <1> pop ebx ; ** ; superblock buffer address 23225 <1> ; 23226 <1> ; ebx = superblock buffer address 23227 <1> ; edx = fbm buffer address + byte offset (dword aligned) 23228 <1> ; ecx = fbm buffer address + 512 23229 <1> alloc_6: 23230 <1> ; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code 23231 <1> ; for Retro UNIX 386 v1.2 23232 <1> ; 25/05/2020 - Retro UNIX 386 v2 code 23233 <1> ; (dword scan) ((1 dword = 32 sectors, 1 byte = 8 sectors)) 23234 <1> ; ((Note: Logical drive size must be multiplies of 32 sectors)) 23235 <1> ; 19/05/2020 23236 <1> ; edx = free blocks map byte address 23237 00004A3B 0FBC02 <1> bsf eax, [edx] ; Scans source operand for first bit set (1). 23238 <1> ; Clear ZF if a bit is found set (1) and 23239 <1> ; loads the destination with an index to 23240 <1> ; first set bit. (0 -> 31) 23241 <1> ; Sets ZF to 1 if no bits are found set. 23242 00004A3E 752A <1> jnz short alloc_8 ; ZF = 0 -> a free block has been found 23243 <1> 23244 00004A40 A1[406D0000] <1> mov eax, [free_map_offset] ; byte offset from start of fbm 23245 00004A45 83C004 <1> add eax, 4 ; next dword 23246 00004A48 3B431C <1> cmp eax, [ebx+SB.FreeMapSize] ; fbm size in bytes 23247 00004A4B 7209 <1> jb short alloc_7 23248 <1> ; invalidate superblock's first free block field 23249 00004A4D C7433CFFFFFFFF <1> mov dword [ebx+SB.FirstFreeBlk], 0FFFFFFFFh 23250 <1> ; 'no free blocks on disk !' error 23251 00004A54 EB8F <1> jmp alloc_2 23252 <1> alloc_7: 23253 <1> ; 26/05/2020 23254 <1> ; NOTE: If ldrv size is not multiplies of 32 sectors, 23255 <1> ; mod (ldrv size / 32) sectors (at the end of ldrv) 23256 <1> ; can not be allocated (for regular files or dirs)! 23257 <1> ; (Kernel or runix fs installation program can use 23258 <1> ; this fact to save/duplicate critical sectors/data 23259 <1> ; onto end sectors of that logical drive's runix fs.) 23260 <1> 23261 <1> ; 26/11/2021 23262 00004A56 A3[406D0000] <1> mov [free_map_offset], eax 23263 <1> ; 28/07/2021 23264 <1> ; set next first free block value for search 23265 00004A5B C1E003 <1> shl eax, 3 ; * 8 ; first free block 23266 <1> ; 26/11/2021 23267 00004A5E 89433C <1> mov [ebx+SB.FirstFreeBlk], eax 23268 <1> ; search (scan) for next free block map dword (in buffer) 23269 00004A61 83C204 <1> add edx, 4 ; next dword 23270 00004A64 39CA <1> cmp edx, ecx 23271 00004A66 72D3 <1> jb short alloc_6 23272 <1> ; 27/11/2021 23273 00004A68 EBA5 <1> jmp short alloc_4 23274 <1> 23275 <1> alloc_8: 23276 <1> ; 26/11/2021 23277 <1> ; convert bit index to xor value 23278 <1> ; and then set allocated flag for corresponding fbm bit 23279 00004A6A 89C1 <1> mov ecx, eax 23280 <1> ;mov cl, al 23281 <1> ;sub eax, eax 23282 <1> ;inc al ; eax = 1 23283 00004A6C B001 <1> mov al, 1 23284 00004A6E D3E0 <1> shl eax, cl 23285 00004A70 3102 <1> xor [edx], eax ; clear allocated block's bit in the fbm 23286 <1> ; zero bit means allocated disk block (1 means free disk block) 23287 <1> 23288 00004A72 A1[406D0000] <1> mov eax, [free_map_offset] ; byte offset from start of fbm 23289 <1> ; note: eax is dword aligned (0,4,8,12..) ! 23290 00004A77 C1E003 <1> shl eax, 3 ; * 8 ; free block number base 23291 00004A7A 01C8 <1> add eax, ecx ; add allocation bit index (0 to 31) 23292 00004A7C 89433C <1> mov [ebx+SB.FirstFreeBlk], eax ; current free block 23293 <1> ; (which is being allocated here) 23294 <1> 23295 <1> ;mov eax, [ebx+SB.FreeMapAddr] 23296 <1> ; ; free blocks map start sector addr 23297 <1> ;add eax, [free_map_index] 23298 <1> 23299 <1> ;;add eax, [ebx+SB.BootSectAddr] 23300 <1> ; ; + Hidden Sectors 23301 <1> ; eax = physical sector number 23302 <1> 23303 <1> ; 27/11/2021 23304 00004A7F A1[486D0000] <1> mov eax, [free_map_sector] ; physical sector number 23305 <1> 23306 00004A84 E86B0F0000 <1> call wslot 23307 <1> ; ebx = buffer data address (write operation bit is set) 23308 <1> ; eax = physical sector number 23309 <1> ; Note: ebx contains addr of the 1st buffer in the buffer 23310 <1> ; (the last allocated buffer becomes the 1st in buffer chain) 23311 <1> 23312 <1> ; 27/11/2021 23313 <1> ;mov [free_map_buffer], ebx ; save free map buffer address 23314 <1> 23315 00004A89 E8730F0000 <1> call dskwr ; writes the 1st buffer to sector 23316 <1> ; (at the beginning/head of the buffer chain) 23317 <1> 23318 <1> ; if we are here, buffer has been written to disk successfully 23319 <1> ; (otherwise cpu would jump to 'error' address) 23320 <1> 23321 <1> ; set superblock modified flag 23322 00004A8E BA[966C0000] <1> mov edx, smod 23323 00004A93 BB[546D0000] <1> mov ebx, systm 23324 00004A98 F605[816C0000]01 <1> test byte [cdev], 1 ; mounted device ? 23325 00004A9F 7406 <1> jz short alloc_9 ; no, root device 23326 <1> ; yes, mounted device 23327 00004AA1 BB[5C6F0000] <1> mov ebx, mount 23328 <1> ;mov edx, mmod 23329 00004AA6 42 <1> inc edx ; edx = offset mmod 23330 <1> alloc_9: 23331 00004AA7 FE02 <1> inc byte [edx] ; superblock modified ! 23332 <1> 23333 <1> ; Allocating a new sector/block (for file) has been completed here. 23334 00004AA9 8B4338 <1> mov eax, [ebx+SB.FreeBlocks] 23335 00004AAC 40 <1> inc eax ; 0FFFFFFFFh -> 0 23336 00004AAD 7405 <1> jz short alloc_10 ; not valid (not set) 23337 00004AAF 48 <1> dec eax ; Free Blocks 23338 00004AB0 48 <1> dec eax ; Free Blocks = Free Blocks - 1 23339 00004AB1 894338 <1> mov [ebx+SB.FreeBlocks], eax 23340 <1> alloc_10: 23341 00004AB4 E89E100000 <1> call get_system_time 23342 <1> ; eax = current time (as unix epoch time) 23343 <1> ; 30/07/2021 23344 00004AB9 89435C <1> mov [ebx+SB.ModifTime], eax 23345 <1> 23346 00004ABC 8B433C <1> mov eax, [ebx+SB.FirstFreeBlk] ; allocated block address 23347 00004ABF FF433C <1> inc dword [ebx+SB.FirstFreeBlk] 23348 <1> ; +1, new value of first free block 23349 <1> ; (new search will be started from here) 23350 <1> ; ((it may not be free, no problem)) 23351 <1> 23352 <1> ; put free map buffer address in ebx 23353 <1> ; 27/11/2021 23354 <1> ;mov ebx, [free_map_buffer] 23355 <1> 23356 00004AC2 C3 <1> retn 23357 <1> 23358 <1> ; 11/02/2022 23359 <1> ; 09/01/2022 23360 <1> ; 27/11/2021 - Retro UNIX 386 v2 fs compatibility modification 23361 <1> free: 23362 <1> ; 12/04/2022 (BugFix) 23363 <1> ; 09/03/2022 23364 <1> ; 11/02/2022 23365 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 23366 <1> ; 05/11/2021 23367 <1> ; 29/10/2021 - temporary (simplified code) 23368 <1> ; 14/08/2021 23369 <1> ; 12/06/2021 23370 <1> ; 07/06/2020 23371 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 23372 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 23373 <1> ; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 23374 <1> ; 23375 <1> ; calculates byte address and bit position for given block number 23376 <1> ; then sets the corresponding bit in the free storage map 23377 <1> ; 23378 <1> ; INPUTS -> 23379 <1> ; r1 - block number for a block structured device 23380 <1> ; cdev - current device 23381 <1> ; OUTPUTS -> 23382 <1> ; free storage map is updated 23383 <1> ; smod is incremented if cdev is root device (fixed disk) 23384 <1> ; mmod is incremented if cdev is a removable disk 23385 <1> ; 23386 <1> ; (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM) 23387 <1> ; ((Modified registers: DX, CX)) 23388 <1> 23389 <1> ; 27/11/2021 23390 <1> ; INPUT: 23391 <1> ; [cdev] = current device (root = 0, mounted = 1) 23392 <1> ; eax = disk block/sector number/address (logical) 23393 <1> ; OUTPUT: 23394 <1> ; ebx = superblock buffer address 23395 <1> ; 23396 <1> ; Note: 23397 <1> ; Free blocks map will be modified and written to it's disk. 23398 <1> ; Superblock (buffer) of [cdev] will be modified and it's 23399 <1> ; modification flag will be set; but the superblock 23400 <1> ; will not be written to it's disk in this 'free' procedure) 23401 <1> ; 23402 <1> ; Modified registers: ebx, ecx, edx, esi, edi, ebp 23403 <1> 23404 <1> ; 27/11/2021 23405 00004AC3 BB[546D0000] <1> mov ebx, systm ; (SuperBlock of root file system) 23406 00004AC8 F605[816C0000]01 <1> test byte [cdev], 1 23407 00004ACF 7405 <1> jz short free_1 23408 00004AD1 BB[5C6F0000] <1> mov ebx, mount ; (SuperBlock of mounted file system) 23409 <1> free_1: ; 1 23410 <1> ; 11/02/2022 23411 <1> ; 27/11/2021 - Retro UNIX 386 v2 file system compatibility code 23412 00004AD6 F6436A01 <1> test byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs 23413 00004ADA 740F <1> jz short free_2 23414 <1> ; 'read only file system' error 23415 00004ADC C705[186D0000]1E00- <1> mov dword [u.error], ERR_READ_ONLY_FS 23416 00004AE4 0000 <1> 23417 00004AE6 E97AE6FFFF <1> jmp error 23418 <1> free_2: 23419 00004AEB 89C1 <1> mov ecx, eax ; logical sector/block number 23420 00004AED A3[486D0000] <1> mov [free_map_sector], eax 23421 00004AF2 C1E903 <1> shr ecx, 3 ; convert to fbmap byte offset 23422 00004AF5 C1E80C <1> shr eax, 12 ; convert to fbmap sector index 23423 <1> ; (1 fb sector for 4096 sectors) 23424 <1> ;and cl, ~3 ; dword alignment (to backward) 23425 <1> ; 11/02/2022 23426 <1> ;and ecx, 511 ; convert to offset within fbm buffer 23427 00004AF8 81E1FC010000 <1> and ecx, 1FCh ; 508, dword aligned offset (32 bit scan) 23428 <1> ; 23429 00004AFE 890D[406D0000] <1> mov [free_map_offset], ecx ; byte position on fbm buffer 23430 <1> ; 27/11/2021 23431 <1> ; eax = fbm sector index 23432 00004B04 034318 <1> add eax, [ebx+SB.FreeMapAddr] 23433 <1> ; free blocks map start sector address 23434 <1> ; 09/01/2022 23435 00004B07 034304 <1> add eax, [ebx+SB.BootSectAddr] 23436 <1> ; + Hidden Sectors 23437 <1> ; 12/04/2022 23438 00004B0A 53 <1> push ebx ; (*) 23439 <1> ; ebx = superblock address 23440 <1> ; eax = physical sector number 23441 00004B0B E8800E0000 <1> call dskrd 23442 <1> ; cpu returns here if there is/was not an error in 'dskrd' 23443 <1> ; eax = physical sector number 23444 <1> ; ebx = (fbm sector) buffer data address 23445 <1> ; 27/11/2021 23446 00004B10 A3[446D0000] <1> mov [free_map_index], eax ; save physical sector address 23447 <1> ; 12/04/2022 23448 00004B15 8B15[406D0000] <1> mov edx, [free_map_offset] ; byte position in fbm buffer 23449 <1> ; 11/02/2022 23450 <1> ;(EDX contains -rounded down- dword aligned offset value) 23451 00004B1B 01DA <1> add edx, ebx ; + (fbm sector) buffer start address 23452 <1> ; 12/04/2022 23453 00004B1D 5B <1> pop ebx ; (*) superblock buffer address 23454 <1> ; 23455 00004B1E 29C0 <1> sub eax, eax 23456 00004B20 A0[486D0000] <1> mov al, [free_map_sector] ; logical sector number 23457 <1> ;and al, 7 23458 <1> ; 11/02/2022 23459 00004B25 241F <1> and al, 31 ; 32 bit fbm scan (with dword aligned offset) 23460 <1> 23461 <1> ; al = bit offset in fbm allocation byte 23462 <1> ; edx = buffer address (start+offset) 23463 <1> ; [free_map_offset] = byte position on fbm 23464 <1> ; 27/11/2021 23465 00004B27 0FAB02 <1> bts [edx], eax ; copy value of bit position in eax to cf 23466 <1> ; then set same bit position at [edx] 23467 00004B2A 7305 <1> jnc short free_3 ; it was allocated sector 23468 <1> 23469 <1> ; already free sector !? 23470 <1> ; (nonsence or defective fs) 23471 <1> 23472 00004B2C 30C0 <1> xor al, al ; 0 ; eax = 0 23473 00004B2E 48 <1> dec eax ; 0FFFFFFFFh 23474 <1> ;mov [ebx+SB.FreeBlocks], eax 23475 <1> ; invalidate free blocks count 23476 00004B2F EB18 <1> jmp short free_5 23477 <1> free_3: 23478 <1> ; 27/11/2021 23479 00004B31 8B4338 <1> mov eax, [ebx+SB.FreeBlocks] 23480 00004B34 40 <1> inc eax 23481 <1> ;jz short free_4 ; 0FFFFFFFFh -> 0 (invalid!) 23482 <1> ; 09/03/2022 23483 00004B35 7501 <1> jnz short free_4 23484 00004B37 48 <1> dec eax ; 0 -> 0FFFFFFFFh (invalid!) 23485 <1> free_4: 23486 00004B38 50 <1> push eax ; * ; number of free blocks 23487 <1> ;mov eax, [free_map_index] ; fbm sector index 23488 <1> ;add eax, [ebx+SB.FreeMapAddr] 23489 <1> ; free blocks map start sector address 23490 <1> ;add eax, [ebx+SB.BootSectAddr] 23491 <1> ; ; + Hidden Sectors 23492 00004B39 A1[446D0000] <1> mov eax, [free_map_index] ; restore physical sector address 23493 <1> ; eax = physical sector number 23494 00004B3E E8B10E0000 <1> call wslot 23495 <1> ; ebx = buffer data address (write operation bit is set) 23496 <1> ; eax = physical sector number 23497 <1> ; Note: ebx contains addr of the 1st buffer in the buffer 23498 <1> ; (the last allocated buffer becomes the 1st in buffer chain) 23499 <1> 23500 00004B43 E8B90E0000 <1> call dskwr ; writes the 1st buffer to sector 23501 <1> ; (at the beginning/head of the buffer chain) 23502 <1> 23503 <1> ; if we are here, buffer has been written to disk successfully 23504 <1> ; (otherwise cpu would jump to 'error' address) 23505 00004B48 58 <1> pop eax ; * ; number of free blocks 23506 <1> free_5: 23507 <1> ; eax = number of free blocks 23508 <1> ; 23509 <1> ; set superblock modified flag 23510 00004B49 BA[966C0000] <1> mov edx, smod 23511 00004B4E BB[546D0000] <1> mov ebx, systm 23512 00004B53 F605[816C0000]01 <1> test byte [cdev], 1 ; mounted device ? 23513 00004B5A 7406 <1> jz short free_6 ; no, root device 23514 <1> ; yes, mounted device 23515 00004B5C BB[5C6F0000] <1> mov ebx, mount 23516 <1> ;mov edx, mmod 23517 00004B61 42 <1> inc edx ; edx = offset mmod 23518 <1> free_6: 23519 00004B62 894338 <1> mov [ebx+SB.FreeBlocks], eax 23520 <1> 23521 00004B65 A1[486D0000] <1> mov eax, [free_map_sector] ; logical sector number 23522 00004B6A 3B433C <1> cmp eax, [ebx+SB.FirstFreeBlk] 23523 00004B6D 7303 <1> jnb short free_7 23524 00004B6F 89433C <1> mov [ebx+SB.FirstFreeBlk], eax 23525 <1> free_7: 23526 00004B72 FE02 <1> inc byte [edx] ; superblock modified ! 23527 00004B74 C3 <1> retn 23528 <1> 23529 <1> iget: 23530 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 23531 <1> ; 30/11/2021 23532 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 23533 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 23534 <1> ; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 23535 <1> ; 23536 <1> ; get a new i-node whose i-number in r1 and whose device is in cdev 23537 <1> ; 23538 <1> ; ('iget' returns current i-number in r1, if input value of r1 is 0) 23539 <1> ; 23540 <1> ; INPUTS -> 23541 <1> ; ii - current i-number, rootdir 23542 <1> ; cdev - new i-node device 23543 <1> ; idev - current i-node device 23544 <1> ; imod - current i-node modified flag 23545 <1> ; mnti - cross device file i-number 23546 <1> ; r1 - i-numbe rof new i-node 23547 <1> ; mntd - mountable device number 23548 <1> ; 23549 <1> ; OUTPUTS -> 23550 <1> ; cdev, idev, imod, ii, r1 23551 <1> ; 23552 <1> ; ((AX = R1)) input/output 23553 <1> ; 23554 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 23555 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 23556 <1> 23557 <1> ; 22/11/2021 23558 <1> ;;mov dl, [cdev] ; 18/07/2013 23559 <1> ;;mov dh, [idev] ; 07/08/2013 23560 <1> ; 26/05/2020 - Retro UNIX 386 v2 23561 <1> ;mov dh, [cdev] 23562 <1> ;mov dl, [idev] 23563 00004B75 668B15[806C0000] <1> mov dx, [idev] ; [idev] in dl, [cdev] in dh 23564 <1> ; 23565 <1> ; 22/11/2021 23566 00004B7C 25FFFF0000 <1> and eax, 0FFFFh 23567 00004B81 3B05[7C6C0000] <1> cmp eax, [ii] 23568 <1> ; cmp r1,ii / r1 = i-number of current file 23569 00004B87 7504 <1> jne short iget_1 23570 <1> ; bne 1f 23571 00004B89 38F2 <1> cmp dl, dh 23572 <1> ; cmp idev,cdev 23573 <1> ; / is device number of i-node = current device 23574 00004B8B 746C <1> je short iget_5 23575 <1> ; ; beq 2f 23576 <1> ; 14/08/2021 23577 <1> iget_1: ; 1: 23578 00004B8D 30DB <1> xor bl, bl 23579 00004B8F 381D[946C0000] <1> cmp [imod], bl ; 0 23580 <1> ; tstb imod / has i-node of current file 23581 <1> ; / been modified i.e., imod set 23582 00004B95 7628 <1> jna short iget_2 23583 <1> ; beq 1f 23584 00004B97 881D[946C0000] <1> mov [imod], bl ; 0 23585 <1> ; clrb imod / if it has, 23586 <1> ; / we must write the new i-node out on disk 23587 <1> ; 22/11/2021 (32 bit push-pop) 23588 00004B9D 50 <1> push eax ; * 23589 <1> ; mov r1,-(sp) 23590 00004B9E 52 <1> push edx ; ** 23591 <1> ; mov cdev,-(sp) 23592 00004B9F A1[7C6C0000] <1> mov eax, [ii] 23593 <1> ; mov ii,r1 23594 <1> ;mov dh, [idev] 23595 <1> ;mov [cdev], dh 23596 <1> ; 09/01/2022 23597 00004BA4 8815[816C0000] <1> mov [cdev], dl ; dl = [idev] 23598 <1> ; mov idev,cdev 23599 00004BAA FEC3 <1> inc bl ; 1 23600 <1> ; 31/07/2013 23601 00004BAC 881D[386D0000] <1> mov [rw], bl ; 1 == write 23602 <1> ;;28/07/2013 rw -> u.rw 23603 <1> ;;mov [u.rw], bl ; 1 == write 23604 00004BB2 E843000000 <1> call icalc 23605 <1> ; jsr r0,icalc; 1 23606 00004BB7 5A <1> pop edx ; ** 23607 00004BB8 8835[816C0000] <1> mov [cdev], dh ; 22/11/2021 23608 <1> ; mov (sp)+,cdev 23609 00004BBE 58 <1> pop eax ; * 23610 <1> ; mov (sp)+,r1 23611 <1> iget_2: ; 1: 23612 <1> ;and ax, ax 23613 00004BBF 21C0 <1> and eax, eax ; 22/11/2021 (32 bit inode number) 23614 <1> ; tst r1 / is new i-number non zero 23615 00004BC1 7431 <1> jz short iget_4 ; 2f 23616 <1> ; beq 2f / branch if r1=0 23617 <1> 23618 <1> ;mov dh, [cdev] 23619 00004BC3 08F6 <1> or dh, dh ; 22/11/2021 23620 <1> ; tst cdev / is the current device number non zero 23621 <1> ; / (i.e., device =/ drum) 23622 00004BC5 7515 <1> jnz short iget_3 ; 1f 23623 <1> ; bne 1f / branch 1f cdev =/ 0 ;; (cdev != 0) 23624 <1> ; 22/11/2021 23625 00004BC7 3B05[8A6C0000] <1> cmp eax, [mnti] 23626 <1> ;cmp ax, [mnti] 23627 <1> ; cmp r1,mnti / mnti is the i-number of the cross device 23628 <1> ; / file (root directory of mounted device) 23629 00004BCD 750D <1> jne short iget_3 ; 1f 23630 <1> ; bne 1f 23631 <1> ;mov bl, [mntd] 23632 00004BCF FEC6 <1> inc dh ; mov dh, 1 ; 22/11/2021 23633 00004BD1 8835[816C0000] <1> mov [cdev], dh ; 22/11/2021 23634 <1> ; mov mntd,cdev / make mounted device the current device 23635 <1> ; 22/11/2021 23636 00004BD7 A1[866C0000] <1> mov eax, [rootdir] ; rootdir = 1 (for runix v2 file system) 23637 <1> ;mov ax, [rootdir] 23638 <1> ; mov rootdir,r1 23639 <1> iget_3: ; 1: 23640 <1> ; 22/11/2021 23641 00004BDC A3[7C6C0000] <1> mov [ii], eax ; 32 bit inode number 23642 <1> ;mov [ii], ax 23643 <1> ; mov r1,ii 23644 <1> ; 30/11/2021 23645 00004BE1 8835[806C0000] <1> mov [idev], dh ; cdev 23646 <1> ;mov [idev], dl ; cdev 23647 <1> ; mov cdev,idev 23648 00004BE7 30DB <1> xor bl, bl 23649 <1> ; 31/07/2013 23650 00004BE9 881D[386D0000] <1> mov [rw], bl ; 0 == read 23651 <1> ;;28/07/2013 rw -> u.rw 23652 <1> ;;mov [u.rw], bl ; 0 = read 23653 00004BEF E806000000 <1> call icalc 23654 <1> ; jsr r0,icalc; 0 / read in i-node ii 23655 <1> iget_4: ; 2: 23656 <1> ; 22/11/2021 23657 00004BF4 A1[7C6C0000] <1> mov eax, [ii] 23658 <1> ;mov ax, [ii] 23659 <1> ; mov ii,r1 23660 <1> iget_5: 23661 00004BF9 C3 <1> retn 23662 <1> ; rts r0 23663 <1> 23664 <1> icalc: 23665 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 23666 <1> ; 28/11/2021 23667 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 23668 <1> ; 02/07/2015 23669 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 23670 <1> ; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 23671 <1> ; 23672 <1> ; calculate physical block number from i-number then 23673 <1> ; read or write that block 23674 <1> ; 23675 <1> ; 'icalc' is called from 'iget' 23676 <1> ; 23677 <1> ; for original unix v1: 23678 <1> ; / i-node i is located in block (i+31.)/16. and begins 32.* 23679 <1> ; / (i+31.) mod 16. bytes from its start 23680 <1> ; 23681 <1> ; for retro unix 8086 v1: 23682 <1> ; i-node is located in block (i+47)/16 and 23683 <1> ; begins 32*(i+47) mod 16 bytes from its start 23684 <1> ; 23685 <1> ; INPUTS -> 23686 <1> ; r1 - i-number of i-node 23687 <1> ; 23688 <1> ; OUTPUTS -> 23689 <1> ; inode r/w 23690 <1> ; 23691 <1> ; ((AX = R1)) input 23692 <1> ; 23693 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 23694 <1> ; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP)) 23695 <1> ; 23696 <1> 23697 <1> ; 28/11/2021 23698 <1> ;cmp byte [idev], 0 ; [cdev] = [idev] 23699 00004BFA 803D[816C0000]00 <1> cmp byte [cdev], 0 23700 00004C01 7607 <1> jna short icalc_0r 23701 00004C03 BD[5C6F0000] <1> mov ebp, mount ; mounted file system's superblock 23702 00004C08 EB05 <1> jmp short icalc_0m 23703 <1> icalc_0r: 23704 <1> ; 28/11/2021 23705 00004C0A BD[546D0000] <1> mov ebp, systm ; root file system's superblock 23706 <1> icalc_0m: 23707 <1> ; 22/11/2021 23708 <1> ;mov edx, eax 23709 00004C0F 8B15[7C6C0000] <1> mov edx, [ii] ; 32 bit inode number 23710 00004C15 8B4528 <1> mov eax, [ebp+SB.InodeTblAddr] ; inode table base address 23711 <1> ; 23712 00004C18 4A <1> dec edx ; 0 based inode number 23713 <1> ; (inode index in inode table) 23714 00004C19 52 <1> push edx ; * 23715 00004C1A C1EA03 <1> shr edx, 3 23716 00004C1D 7402 <1> jz short icalc_0t ; 0 for inodes 1 to 8 23717 00004C1F 01D0 <1> add eax, edx 23718 <1> icalc_0t: 23719 <1> ; 09/01/2022 23720 <1> ; eax = locical block/sector number 23721 00004C21 034504 <1> add eax, [ebp+SB.BootSectAddr] 23722 <1> ; eax = physical block/sector number 23723 00004C24 E8670D0000 <1> call dskrd 23724 <1> ; jsr r0,dskrd / read in block containing i-node i. 23725 <1> ; 31/07/2013 23726 00004C29 803D[386D0000]00 <1> cmp byte [rw], 0 ; Retro Unix 8086 v1 feature ! 23727 <1> ;; 28/07/2013 rw -> u.rw 23728 <1> ;;cmp byte [u.rw], 0 ; Retro Unix 8086 v1 feature ! 23729 <1> ; tst (r0) 23730 00004C30 7605 <1> jna short icalc_1 23731 <1> ; beq 1f / branch to wslot when argument 23732 <1> ; / in icalc call = 1 23733 <1> ; eAX = r1 = block number 23734 00004C32 E8BD0D0000 <1> call wslot 23735 <1> ; jsr r0,wslot / set up data buffer for write 23736 <1> ; / (will be same buffer as dskrd got) 23737 <1> ; EBX = r5 points to first word in data area for this block 23738 <1> icalc_1: ; 1: 23739 00004C37 5A <1> pop edx ; * 23740 <1> ; 22/11/2021 23741 00004C38 83E207 <1> and edx, 07h ; 8 inodes per inode table sector 23742 00004C3B C1E206 <1> shl edx, 6 ; * 64 (inode size) 23743 <1> ; edx = 64 * (mod(inodenumber-1)/8) 23744 00004C3E 89DE <1> mov esi, ebx ; ebx points to 1st word of the buffer 23745 00004C40 01D6 <1> add esi, edx ; edx is inode offset in the buffer 23746 <1> ; eSI (r5) points to first word in i-node i. 23747 <1> ; mov (sp)+,mq / calculate offset in data buffer; 23748 <1> ; / 32.*(i+31.)mod16 23749 <1> ; mov $5,lsh / for i-node i. 23750 <1> ; add mq,r5 / r5 points to first word in i-node i. 23751 00004C42 BF[24680000] <1> mov edi, inode 23752 <1> ; mov $inode,r1 / inode is address of first word 23753 <1> ; / of current i-node 23754 <1> ;mov ecx, 8 ; 02/07/2015 (32 bit modification) 23755 <1> ; ; mov $16.,r3 23756 <1> ; 28/11/2021 23757 00004C47 29C9 <1> sub ecx, ecx 23758 00004C49 B110 <1> mov cl, 16 ; Retro UNIX 386 v2 inode size = 64 bytes 23759 <1> ; 31/07/2013 23760 00004C4B 382D[386D0000] <1> cmp [rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 23761 <1> ;;28/07/2013 rw -> u.rw 23762 <1> ;;cmp [u.rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 23763 <1> ; tst (r0)+ / branch to 2f when argument in icalc call = 0 23764 00004C51 7609 <1> jna short icalc_3 23765 <1> ; beq 2f / r0 now contains proper return address 23766 <1> ; / for rts r0 23767 <1> icalc_2: ; 1: 23768 00004C53 87F7 <1> xchg esi, edi 23769 <1> ; overwrite old i-node (in buffer to be written) 23770 00004C55 F3A5 <1> rep movsd 23771 <1> ; mov (r1)+,(r5)+ / over write old i-node 23772 <1> ; dec r3 23773 <1> ; bgt 1b 23774 <1> ;call dskwr 23775 <1> ; ; jsr r0,dskwr / write inode out on device 23776 <1> ;retn 23777 <1> ; ; rts r0 23778 <1> ; 28/11/2021 23779 00004C57 E9A50D0000 <1> jmp dskwr 23780 <1> icalc_3: ; 2: 23781 <1> ; copy new i-node into inode area of (core) memory 23782 00004C5C F3A5 <1> rep movsd 23783 <1> ; mov (r5)+,(r1)+ / read new i-node into 23784 <1> ; / "inode" area of core 23785 <1> ; dec r3 23786 <1> ; bgt 2b 23787 00004C5E C3 <1> retn 23788 <1> ; rts r0 23789 <1> 23790 <1> access: 23791 <1> ; 13/03/2022 23792 <1> ; 25/12/2021 23793 <1> ; 19/12/2021 23794 <1> ; 28/11/2021 23795 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 23796 <1> ; 31/10/2021 - temporary (simplified code) 23797 <1> ; 14/06/2021 23798 <1> ; 02/05/2021 23799 <1> ; 27/03/2021 23800 <1> ; 26/03/2021 23801 <1> ; 25/03/2021 23802 <1> ; 23/03/2021 (Retro UNIX 386 v2 - Beginning) 23803 <1> ; ((ref: unix v7 source - fio.c)) 23804 <1> ; ref: INODE STRUCTURE of Retro UNIX v2 file system 23805 <1> ; 07/02/2020, 'RETRO UNIX v2 Inodes.pdf' 23806 <1> ; 23807 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 23808 <1> ; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1) 23809 <1> ; 23810 <1> ; check whether user is owner of file or user has read or write 23811 <1> ; permission (based on i.flgs). 23812 <1> ; 23813 <1> ; INPUTS -> 23814 <1> ; r1 - i-number of file 23815 <1> ; u.uid 23816 <1> ; arg0 -> (owner flag mask) 23817 <1> ; Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 23818 <1> ; OUTPUTS -> 23819 <1> ; inode (or jump to error) 23820 <1> ; 23821 <1> ; ((AX = R1)) input/output 23822 <1> ; 23823 <1> ; ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP)) 23824 <1> 23825 <1> ; 26/03/2021 23826 <1> ; INPUT: 23827 <1> ; eax = inode number (ax) 23828 <1> ; dx = mode (IEXEC, IREAD or IWRITE) 23829 <1> ; [cdev] = logical drive number ; 31/10/2021 23830 <1> ; 23831 <1> ; OUTPUT: 23832 <1> ; inode (or jump to error) 23833 <1> ; eax (ax) = [ii] = inode number 23834 <1> ; [cdev] = logical drive number ; 31/10/2021 23835 <1> ; 23836 <1> ; Modified registers: (eax), ebx, ecx, edx, esi, edi, ebp 23837 <1> ; 23838 <1> ; IREAD equ 100h ; read permission flag, owner 23839 <1> ; IWRITE equ 80h ; write permission flag, owner 23840 <1> ; IEXEC equ 40h ; execute permission flag, owner 23841 <1> 23842 <1> ; 23/03/2021 23843 00004C5F 52 <1> push edx ; save flag (DX) 23844 <1> ;push dx ; save flag (DL) 23845 00004C60 E810FFFFFF <1> call iget 23846 <1> ; jsr r0,iget / read in i-node for current directory 23847 <1> ; / (i-number passed in r1) 23848 <1> ;;mov cl, [i.flgs] 23849 <1> ;; ; mov i.flgs,r2 23850 <1> ; 23/03/2021 23851 <1> ;mov cx, [i.iflgs] 23852 <1> 23853 <1> ;;pop dx ; restore flag (DL) 23854 <1> ; 23/03/2021 23855 00004C65 5A <1> pop edx ; restore flag (DX) 23856 <1> 23857 <1> ; 28/11/2021 (iget will not return here if there is an error) 23858 <1> ; 31/10/2021 23859 <1> ;jc short access_5 23860 <1> 23861 <1> ; 31/10/2021 23862 <1> ; Note: If eax input is same with [mnti], 'iget' will change 23863 <1> ; [cdev] to 1 and eax will be 1 (root dir of mounted fs) 23864 <1> 23865 <1> ; 27/03/2021 23866 <1> ; 23/03/2021 23867 <1> ; (check if it is write permission flag) 23868 00004C66 6681FA8000 <1> cmp dx, 80h ; IWRITE 23869 00004C6B 775E <1> ja short access_r ; IREAD = 100h (owner) 23870 00004C6D 722B <1> jb short access_x ; IEXEC = 40h (owner) 23871 <1> ; IWRITE (80h) 23872 <1> access_w: 23873 <1> ; 23/03/2021 23874 <1> ; ((ref: Retro UNIX 386 v2, 'ux.s', 'ldrv' structure)) 23875 <1> ;mov bl, [idev] 23876 <1> ;call getfs 23877 <1> ;movzx ebx, byte [idev] ; logical drive number 23878 <1> ;shl bx, 6 ; * 64 ; of current inode 23879 <1> ;add ebx, ldrvtable 23880 <1> ;;test byte [ebx+ldrv.pflags], 01h ; read only fs flag 23881 <1> ;;jz short access_0 23882 <1> ;; 14/06/2021 23883 <1> ; 14/06/2021 23884 <1> ; check block device (fs) if it is read only fs or not ? 23885 <1> ;mov edi, [ebx+ldrv.superblk] 23886 <1> ;test byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ? 23887 <1> ;jz short access_0 23888 <1> ; 31/10/2021 23889 00004C6F 803D[816C0000]01 <1> cmp byte [cdev], 1 23890 00004C76 7207 <1> jb short access_7 ; [cdev] = 0 23891 <1> ; [cdev] = 1 23892 <1> ; 28/11/2021 23893 00004C78 BF[5C6F0000] <1> mov edi, mount ; mounted file system's superblock buffer 23894 00004C7D EB05 <1> jmp short access_8 23895 <1> access_7: 23896 <1> ; 28/11/2021 23897 00004C7F BF[546D0000] <1> mov edi, systm ; root file system's superblock buffer 23898 <1> access_8: 23899 00004C84 F6476A01 <1> test byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ? 23900 00004C88 7441 <1> jz short access_0 23901 <1> 23902 <1> ; 23/03/2021 23903 <1> ;mov dword [u.error], ERR_READ_ONLY_FS 23904 <1> ; ; 'read only file system !' error 23905 <1> ;jmp error 23906 <1> 23907 <1> ; 19/12/2021 23908 00004C8A F605[25680000]80 <1> test byte [i.flgs+1], 80h ; regular file ? 23909 00004C91 7438 <1> jz short access_0 ; no, device file 23910 <1> 23911 <1> ; 31/10/2021 23912 00004C93 B81E000000 <1> mov eax, ERR_READ_ONLY_FS 23913 <1> ; 'read only file system !' error 23914 <1> ; 27/03/2021 23915 00004C98 EB27 <1> jmp short access_5 23916 <1> 23917 <1> ; check block device (fs) if it is read only fs or not ? 23918 <1> 23919 <1> ;mov dh, [u.uid] 23920 <1> ;cmp dh, [i.uid] 23921 <1> ; ; cmpb i.uid,u.uid / is user same as owner of file 23922 <1> ;jne short access_1 23923 <1> ; bne 1f / no, then branch 23924 <1> access_x: 23925 <1> ; IEXEC (40h) 23926 <1> ; 27/03/2021 23927 00004C9A 668B1D[24680000] <1> mov bx, [i.flgs] 23928 00004CA1 F6C780 <1> test bh, 80h ; regular file ? 23929 00004CA4 7416 <1> jz short access_4 ; not executable file ! 23930 00004CA6 F6C740 <1> test bh, 40h ; directory ? 23931 00004CA9 7511 <1> jnz short access_4 ; not executable file ! 23932 00004CAB 668B0D[F66C0000] <1> mov cx, [u.uid] 23933 00004CB2 6609C9 <1> or cx, cx 23934 00004CB5 7520 <1> jnz short access_3 ; (restricted user) 23935 <1> ; (super user) 23936 <1> ;test [i.flgs], dl ; execute permission for owner 23937 <1> ;test byte [i.flgs], 49h ; for owner, group, others 23938 00004CB7 F6C349 <1> test bl, 49h ; exec perm for owner, group, others 23939 00004CBA 7549 <1> jnz short access_2 23940 <1> access_4: 23941 <1> ; 31/10/2021 23942 00004CBC B816000000 <1> mov eax, ERR_NOT_EXECUTABLE 23943 <1> ; 'not executable file !' error 23944 <1> ; 26/03/2021 23945 <1> ;;sysexec_not_exf: 23946 <1> ; mov dword [u.error], ERR_NOT_EXECUTABLE 23947 <1> ; ; 'not executable file !' error 23948 <1> ;access_5: 23949 <1> ; jmp error 23950 <1> 23951 <1> ; 31/10/2021 23952 <1> access_5: 23953 00004CC1 A3[186D0000] <1> mov [u.error], eax 23954 00004CC6 E99AE4FFFF <1> jmp error 23955 <1> 23956 <1> access_r: 23957 <1> ; 27/03/2021 23958 <1> access_0: 23959 <1> ; 23/03/2021 23960 00004CCB 668B0D[F66C0000] <1> mov cx, [u.uid] 23961 00004CD2 6609C9 <1> or cx, cx ; 0 ; root ? 23962 <1> ;jz short access_2 ; yes 23963 <1> ; 25/12/2021 23964 00004CD5 741E <1> jz short access_1 ; yes 23965 <1> access_3: 23966 <1> ; 13/03/2022 23967 00004CD7 663B0D[28680000] <1> cmp cx, [i.uid] ; owner ? 23968 00004CDE 7415 <1> je short access_1 ; yes 23969 <1> ;; owner ? 23970 00004CE0 8A1D[2A680000] <1> mov bl, [i.gid] 23971 <1> ;cmp cx, [i.uid] 23972 <1> ;;je short access_1 23973 <1> ;; 02/05/2021 23974 <1> ;jne short access_6 23975 <1> ; 13/03/2022 23976 <1> ; same group ? 23977 00004CE6 66C1EA03 <1> shr dx, 3 23978 <1> ; check owner's group number/ID 23979 00004CEA 3A1D[FA6C0000] <1> cmp bl, [u.gid] ; same group number/ID ? 23980 00004CF0 7403 <1> je short access_1 ; yes 23981 <1> ; one of others 23982 <1> ;shr dx, 6 23983 <1> ;jmp short access_1 ; others 23984 <1> ; 13/03/2022 23985 <1> ; one of others 23986 00004CF2 C0EA03 <1> shr dl, 3 23987 <1> ; ; 13/03/2022 23988 <1> ; jmp short access_1 ; others 23989 <1> ;access_6: 23990 <1> ; ;shr cl, 2 23991 <1> ; ; ; asrb r2 / shift owner read write bits into non owner 23992 <1> ; ; ; ; / read/write bits 23993 <1> ; ; ; asrb r2 23994 <1> ; 23995 <1> ; ; 23/03/2021 23996 <1> ; ; same group ? 23997 <1> ; shr dx, 3 23998 <1> ; ;mov cl, [u.gid] 23999 <1> ; ;cmp cl, [i.gid] 24000 <1> ; ;je short access_1 24001 <1> ; ; 02/05/2021 24002 <1> ; cmp bl, [u.gid] 24003 <1> ; je short access_1 ; same group, different owner 24004 <1> ; 24005 <1> ; ; others 24006 <1> ; ;shr dx, 3 24007 <1> ; shr dl, 3 24008 <1> ; ;jmp short access_1 24009 <1> ; 24010 <1> ;;access_1: ; 1: 24011 <1> ; ;and cl, dl 24012 <1> ; ; ; bit r2,(r0)+ / test read-write flags against argument 24013 <1> ; ; ; / in access call 24014 <1> ; ;jnz short access_2 24015 <1> ; ; ; bne 1f 24016 <1> ; 24017 <1> ; ;or dh, dh ; super user (root) ? 24018 <1> ; ; ; tstb u.uid 24019 <1> ; ;jz short access_2 ; yes, super user 24020 <1> ; ;;jnz error 24021 <1> ; ; ; beq 1f 24022 <1> ; ; ; jmp error 24023 <1> ; 24024 <1> ; ;mov dword [u.error], ERR_FILE_ACCESS 24025 <1> ; ; ; 'permission denied !' error 24026 <1> ; ;jmp error 24027 <1> 24028 <1> access_1: 24029 <1> ; 23/03/2021 24030 00004CF5 668515[24680000] <1> test dx, [i.flgs] 24031 00004CFC 7507 <1> jnz short access_2 24032 <1> 24033 <1> ;; r/w permission error 24034 <1> ;mov dword [u.error], ERR_FILE_ACCESS 24035 <1> ; ; 'permission denied !' error 24036 <1> ;;jmp error 24037 <1> 24038 <1> ; 31/10/2021 24039 00004CFE B80B000000 <1> mov eax, ERR_FILE_ACCESS 24040 <1> ; 'permission denied !' error 24041 <1> ; 27/03/2021 24042 00004D03 EBBC <1> jmp short access_5 24043 <1> 24044 <1> access_2: ; 1: 24045 <1> ;; DL = flags 24046 <1> ;retn 24047 <1> ; ; rts r0 24048 <1> ; 27/03/2021 24049 <1> ; DX = flag (100h-20h-04h or 80h-10h-02h or 40h-08h-01h) 24050 00004D05 C3 <1> retn 24051 <1> 24052 <1> ; 12/01/2022 - Retro UNIX 386 v1.2 24053 <1> %if 0 24054 <1> 24055 <1> setimod: 24056 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 24057 <1> ; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 24058 <1> ; 24059 <1> ; 'setimod' sets byte at location 'imod' to 1; thus indicating that 24060 <1> ; the inode has been modified. Also puts the time of modification 24061 <1> ; into the inode. 24062 <1> ; 24063 <1> ; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM) 24064 <1> ; ((Modified registers: eDX, eCX, eBX)) 24065 <1> ; 24066 <1> 24067 <1> ;push edx 24068 <1> push eax 24069 <1> 24070 <1> mov byte [imod], 1 24071 <1> ; movb $1,imod / set current i-node modified bytes 24072 <1> ; Erdogan Tan 14-7-2012 24073 <1> call epoch 24074 <1> ; mov s.time,i.mtim 24075 <1> ; / put present time into file modified time 24076 <1> ; mov s.time+2,i.mtim+2 24077 <1> 24078 <1> mov [i.mtim], eax 24079 <1> 24080 <1> ; Retro UNIX 386 v1 modification ! (cmp) 24081 <1> ; Retro UNIX 8086 v1 modification ! (test) 24082 <1> cmp dword [i.ctim], 0 24083 <1> jnz short setimod_ok 24084 <1> 24085 <1> mov [i.ctim], eax 24086 <1> 24087 <1> setimod_ok: ; 31/07/2013 24088 <1> pop eax 24089 <1> ;pop edx 24090 <1> 24091 <1> retn 24092 <1> ; rts r0 24093 <1> %endif 24094 <1> 24095 <1> setimod: 24096 <1> ; 12/01/2022 - Retro UNIX 386 v1.2 24097 <1> ; 25/05/2020 - Retro UNIX 386 v2 24098 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 24099 <1> ; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 24100 <1> ; 24101 <1> ; 'setimod' sets byte at location 'imod' to 1; thus indicating that 24102 <1> ; the inode has been modified. Also puts the time of modification 24103 <1> ; into the inode. 24104 <1> ; 24105 <1> ; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM) 24106 <1> ; ((Modified registers: eDX, eCX, eBX)) 24107 <1> ; 24108 <1> 24109 <1> ; Reference: 24110 <1> ; 25/01/2020 - 'UNIXHDCP.ASM', 'setimod' procedure 24111 <1> ; (Retro UNIX 386 v2 file system installation utility) 24112 <1> 24113 <1> ; 25/05/2020 24114 <1> ; 24115 <1> ; INPUT: 24116 <1> ; none 24117 <1> ; OUTPUT: 24118 <1> ; inode times and [imod] will be set 24119 <1> ; ([imodx] will be reset) 24120 <1> ; cf = 0 24121 <1> 24122 <1> ; Modified registers: ecx, (edx)? 24123 <1> 24124 <1> ;push edx 24125 00004D06 50 <1> push eax 24126 <1> 24127 00004D07 C605[946C0000]01 <1> mov byte [imod], 1 24128 <1> ; movb $1,imod / set current i-node modified bytes 24129 <1> 24130 <1> ; 25/05/2020 - Retro UNIX 386 v2 24131 00004D0E A1[60680000] <1> mov eax, [i.ctim] ; inode (file) creation time 24132 00004D13 21C0 <1> and eax, eax 24133 00004D15 7518 <1> jnz short setimod_4 24134 <1> 24135 <1> ; New file 24136 <1> setimod_1: 24137 <1> ; 25/05/2020 - Retro UNIX 386 v2 by Erdogan Tan 24138 <1> ; (Modified UNIX v7 inode and new FS construction) 24139 <1> ; 24140 00004D17 E83B0E0000 <1> call get_system_time ; get current (unix epoch) time 24141 <1> 24142 <1> ;; Erdogan Tan 14-7-2012 24143 <1> ;call epoch 24144 <1> ; ; mov s.time,i.mtim 24145 <1> ; ; / put present time into file modified time 24146 <1> ; ; mov s.time+2,i.mtim+2 24147 <1> ; 24148 <1> ;mov [i.mtim], eax 24149 <1> 24150 <1> ; Retro UNIX 386 v1 modification ! (cmp) 24151 <1> ; Retro UNIX 8086 v1 modification ! (test) 24152 <1> ;cmp dword [i.ctim], 0 24153 <1> ;jnz short setimod_ok 24154 <1> 24155 00004D1C A3[60680000] <1> mov [i.ctim], eax 24156 <1> 24157 <1> ; 25/05/2020 24158 00004D21 EB05 <1> jmp short setimod_3 24159 <1> 24160 <1> setimod_2: 24161 <1> ; File/Directory data (file size or content) is changed 24162 <1> ; This is last modification date&time 24163 00004D23 A3[5C680000] <1> mov [i.mtim], eax 24164 <1> setimod_3: 24165 <1> ; 19/09/2019 ('UNIXHDCP.ASM', 'setimod' by Erdogan Tan) 24166 <1> ; This is last access or last changing date&time 24167 <1> ; of inode (chmod,chown,chgrp,link) 24168 <1> ; parameters (without file/dir data changing) 24169 00004D28 A3[58680000] <1> mov [i.atim], eax 24170 <1> 24171 <1> setimod_ok: ; 31/07/2013 24172 00004D2D 58 <1> pop eax 24173 <1> ;pop edx 24174 <1> 24175 00004D2E C3 <1> retn 24176 <1> ; rts r0 24177 <1> setimod_4: 24178 <1> ; 25/05/2020 - Retro UNIX 386 v2 24179 00004D2F 31C9 <1> xor ecx, ecx 24180 00004D31 390D[5C680000] <1> cmp [i.mtim], ecx ; 0 24181 00004D37 76EA <1> jna short setimod_2 24182 <1> 24183 00004D39 E8190E0000 <1> call get_system_time ; get current (unix epoch) time 24184 <1> ; ((system time will be updated directly by timer interrupt)) 24185 <1> 24186 00004D3E 803D[956C0000]00 <1> cmp byte [imodx], 0 ; flag means "file/dir data is same but 24187 00004D45 76DC <1> jna short setimod_2 ; inode has been changed" 24188 <1> 24189 <1> ; File/Dir data (File size or content) is same but 24190 <1> ; inode's mode, link count, owner or group id has been changed 24191 <1> ; (so, we do not change last modification date&time) 24192 00004D47 C605[956C0000]00 <1> mov byte [imodx], 0 ; reset inode modified (extended) flag 24193 00004D4E EBD8 <1> jmp short setimod_3 24194 <1> 24195 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 24196 <1> %if 0 24197 <1> ; Retro UNIX 386 v1.1 'itrunc' code 24198 <1> itrunc: 24199 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 24200 <1> ; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 24201 <1> ; 24202 <1> ; 'itrunc' truncates a file whose i-number is given in r1 24203 <1> ; to zero length. 24204 <1> ; 24205 <1> ; INPUTS -> 24206 <1> ; r1 - i-number of i-node 24207 <1> ; i.dskp - pointer to contents or indirect block in an i-node 24208 <1> ; i.flgs - large file flag 24209 <1> ; i.size - size of file 24210 <1> ; 24211 <1> ; OUTPUTS -> 24212 <1> ; i.flgs - large file flag is cleared 24213 <1> ; i.size - set to 0 24214 <1> ; i.dskp .. i.dskp+16 - entire list is cleared 24215 <1> ; setimod - set to indicate i-node has been modified 24216 <1> ; r1 - i-number of i-node 24217 <1> ; 24218 <1> ; ((AX = R1)) input/output 24219 <1> ; 24220 <1> ; (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM) 24221 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 24222 <1> 24223 <1> call iget 24224 <1> ; jsr r0,iget 24225 <1> mov esi, i.dskp 24226 <1> ; mov $i.dskp,r2 / address of block pointers in r2 24227 <1> xor eax, eax 24228 <1> itrunc_1: ; 1: 24229 <1> lodsw 24230 <1> ; mov (r2)+,r1 / move physical block number into r1 24231 <1> or ax, ax 24232 <1> jz short itrunc_5 24233 <1> ; beq 5f 24234 <1> push esi 24235 <1> ; mov r2,-(sp) 24236 <1> test word [i.flgs], 1000h 24237 <1> ; bit $10000,i.flgs / test large file bit? 24238 <1> jz short itrunc_4 24239 <1> ; beq 4f / if clear, branch 24240 <1> push eax 24241 <1> ; mov r1,-(sp) / save block number of indirect block 24242 <1> call dskrd 24243 <1> ; jsr r0,dskrd / read in block, 1st data word 24244 <1> ; / pointed to by r5 24245 <1> ; eBX = r5 = Buffer data address (the 1st word) 24246 <1> mov ecx, 256 24247 <1> ; mov $256.,r3 / move word count into r3 24248 <1> mov esi, ebx 24249 <1> itrunc_2: ; 2: 24250 <1> lodsw 24251 <1> ; mov (r5)+,r1 / put 1st data word in r1; 24252 <1> ; / physical block number 24253 <1> and ax, ax 24254 <1> jz short itrunc_3 24255 <1> ; beq 3f / branch if zero 24256 <1> ;push ecx 24257 <1> push cx 24258 <1> ; mov r3,-(sp) / save r3, r5 on stack 24259 <1> ;push esi 24260 <1> ; mov r5,-(sp) 24261 <1> call free 24262 <1> ; jsr r0,free / free block in free storage map 24263 <1> ;pop esi 24264 <1> ; mov(sp)+,r5 24265 <1> pop cx 24266 <1> ;pop ecx 24267 <1> ; mov (sp)+,r3 24268 <1> itrunc_3: ; 3: 24269 <1> loop itrunc_2 24270 <1> ; dec r3 / decrement word count 24271 <1> ; bgt 2b / branch if positive 24272 <1> pop eax 24273 <1> ; mov (sp)+,r1 / put physical block number of 24274 <1> ; / indirect block 24275 <1> ; 01/08/2013 24276 <1> and word [i.flgs], 0EFFFh ; 1110111111111111b 24277 <1> itrunc_4: ; 4: 24278 <1> call free 24279 <1> ; jsr r0,free / free indirect block 24280 <1> pop esi 24281 <1> ; mov (sp)+,r2 24282 <1> itrunc_5: ; 5: 24283 <1> cmp esi, i.dskp+16 24284 <1> ; cmp r2,$i.dskp+16. 24285 <1> jb short itrunc_1 24286 <1> ; bne 1b / branch until all i.dskp entries check 24287 <1> ; 01/08/2013 24288 <1> ;and word [i.flgs], 0EFFFh ; 1110111111111111b 24289 <1> ; bic $10000,i.flgs / clear large file bit 24290 <1> mov edi, i.dskp 24291 <1> mov cx, 8 24292 <1> xor ax, ax 24293 <1> mov [i.size], ax ; 0 24294 <1> ; clr i.size / zero file size 24295 <1> rep stosw 24296 <1> ; jsr r0,copyz; i.dskp; i.dskp+16. 24297 <1> ; / zero block pointers 24298 <1> call setimod 24299 <1> ; jsr r0,setimod / set i-node modified flag 24300 <1> mov ax, [ii] 24301 <1> ; mov ii,r1 24302 <1> retn 24303 <1> ; rts r0 24304 <1> 24305 <1> ; Retro UNIX 386 v1.1 'imap' code 24306 <1> imap: 24307 <1> ; 17/07/2022 (Retro UNIX 386 v1.2) 24308 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 24309 <1> ; 26/04/2013 (Retro UNIX 8086 v1) 24310 <1> ; 24311 <1> ; 'imap' finds the byte in core (superblock) containing 24312 <1> ; allocation bit for an i-node whose number in r1. 24313 <1> ; 24314 <1> ; INPUTS -> 24315 <1> ; r1 - contains an i-number 24316 <1> ; fsp - start of table containing open files 24317 <1> ; 24318 <1> ; OUTPUTS -> 24319 <1> ; r2 - byte address of byte with the allocation bit 24320 <1> ; mq - a mask to locate the bit position. 24321 <1> ; (a 1 is in calculated bit posisiton) 24322 <1> ; 24323 <1> ; ((AX = R1)) input/output 24324 <1> ; ((DL/DX = MQ)) output 24325 <1> ; ((BX = R2)) output 24326 <1> ; 24327 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 24328 <1> ; ((Modified registers: eDX, eCX, eBX, eSI)) 24329 <1> ; 24330 <1> ; / get the byte that has the allocation bit for 24331 <1> ; / the i-number contained in r1 24332 <1> ;mov dx, 1 24333 <1> mov dl, 1 24334 <1> ; mov $1,mq / put 1 in the mq 24335 <1> movzx ebx, ax 24336 <1> ; mov r1,r2 / r2 now has i-number whose byte 24337 <1> ; / in the map we must find 24338 <1> sub bx, 41 24339 <1> ; sub $41.,r2 / r2 has i-41 24340 <1> mov cl, bl 24341 <1> ; mov r2,r3 / r3 has i-41 24342 <1> and cl, 7 24343 <1> ; bic $!7,r3 / r3 has (i-41) mod 8 to get 24344 <1> ; / the bit position 24345 <1> jz short imap1 24346 <1> ;shl dx, cl 24347 <1> shl dl, cl 24348 <1> ; mov r3,lsh / move the 1 over (i-41) mod 8 positions 24349 <1> imap1: ; / to the left to mask the correct bit 24350 <1> ;shr bx, 3 24351 <1> ; 17/07/2022 24352 <1> shr ebx, 3 24353 <1> ; asr r2 24354 <1> ; asr r2 24355 <1> ; asr r2 / r2 has (i-41) base 8 of the byte number 24356 <1> ; / from the start of the map 24357 <1> ; mov r2,-(sp) / put (i-41) base 8 on the stack 24358 <1> mov esi, systm 24359 <1> ; mov $systm,r2 / r2 points to the in-core image of 24360 <1> ; / the super block for drum 24361 <1> ;cmp word [cdev], 0 24362 <1> cmp byte [cdev], 0 24363 <1> ; tst cdev / is the device the disk 24364 <1> jna short imap2 24365 <1> ; beq 1f / yes 24366 <1> add esi, mount - systm 24367 <1> ; add $mount-systm,r2 / for mounted device, 24368 <1> ; / r2 points to 1st word of its super block 24369 <1> imap2: ; 1: 24370 <1> add bx, [esi] ;; add free map size to si 24371 <1> ; add (r2)+,(sp) / get byte address of allocation bit 24372 <1> add bx, 4 24373 <1> add ebx, esi 24374 <1> ; add (sp)+,r2 / ? 24375 <1> ;add ebx, 4 ;; inode map offset in superblock 24376 <1> ;; (2 + free map size + 2) 24377 <1> ; add $2,r2 / ? 24378 <1> ; DL/DX (MQ) has a 1 in the calculated bit position 24379 <1> ; BX (R2) has byte address of the byte with allocation bit 24380 <1> retn 24381 <1> ; rts r0 24382 <1> %endif 24383 <1> 24384 <1> ; Retro UNIX 386 v2.0 'itrunc' code 24385 <1> itrunc: 24386 <1> ; 26/03/2022 24387 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 24388 <1> ; 07/06/2020 24389 <1> ; 02/06/2020 24390 <1> ; 26/05/2020 - Retro UNIX 386 v2 24391 <1> ; 24392 <1> ; 'itrunc' truncates a file whose i-number is given in r1 24393 <1> ; to zero length. 24394 <1> ; 07/06/2020 24395 <1> ; 02/06/2020 24396 <1> ; 26/05/2020 - Retro UNIX 386 v2 24397 <1> ; 24398 <1> ; 'itrunc' truncates a file whose i-number is given 24399 <1> ; in ax to zero length. 24400 <1> ; 24401 <1> 24402 <1> ; Reference: 24403 <1> ; Retro UNIX 386 v2 FS installation utility 24404 <1> ; 17/01/2020 - 'UNIXHDCP.ASM', 'itrunc' procedure 24405 <1> 24406 <1> ; * Free all the disk blocks associated 24407 <1> ; * with the specified inode structure. 24408 <1> 24409 <1> ; INPUT: 24410 <1> ; (e)ax = inode number 24411 <1> ; OUTPUT: 24412 <1> ; inode will be modified (file size = 0) 24413 <1> ; ; 26/03/20221 24414 <1> ; eax = 0 (if cf=0) 24415 <1> 24416 <1> ; (Modified registers: eax, edx, ecx, ebx, esi, edi, ebp) 24417 <1> 24418 <1> ; 07/06/2020 24419 <1> 24420 <1> ; [cdev] = current logical drive number 24421 <1> ; eax = inode number (for [cdev]) 24422 <1> 24423 00004D50 E820FEFFFF <1> call iget 24424 <1> ; 10/01/2022 24425 <1> ;jc short itrunc_0 ; error code in eax (al) 24426 <1> 24427 <1> ; eax = inode number, [ii] 24428 <1> ; [cdev] = current logical drive number (same with input) 24429 <1> ; [idev] = logical drive number of current inode, [ii] 24430 <1> ; [ii] = current inode ([ii] = ax input, if ax was not zero) 24431 <1> ; [imod] = 0 24432 <1> ; ([imodx] = 0) 24433 <1> 24434 00004D55 F605[25680000]80 <1> test byte [i.flgs+1], 80h ; regular file or directory 24435 00004D5C 750F <1> jnz short itrunc_1 24436 <1> 24437 <1> ; 10/01/2022 24438 00004D5E C705[186D0000]FF00- <1> mov dword [u.error], ERR_NOT_REGULAR ; 255 24439 00004D66 0000 <1> 24440 <1> ; 'not a regular file (or directory) !' error 24441 <1> itrunc_0: 24442 00004D68 E9F8E3FFFF <1> jmp error 24443 <1> itrunc_1: 24444 00004D6D F605[25680000]10 <1> test byte [i.flgs+1], 10h ; large file (indirect blocks) 24445 00004D74 7528 <1> jnz short itrunc_5 ; large file 24446 00004D76 BE[30680000] <1> mov esi, i.dskp ; disk address pointer 0 24447 <1> itrunc_2: 24448 00004D7B AD <1> lodsd 24449 00004D7C 21C0 <1> and eax, eax 24450 00004D7E 740C <1> jz short itrunc_3 ; empty ! (no more sectors/blocks) 24451 <1> ; eax = block address to be released 24452 00004D80 56 <1> push esi ; * ; 10/01/2022 24453 00004D81 E83DFDFFFF <1> call free 24454 <1> ; modified registers: ebx, ecx, edx, esi, edi, ebp 24455 <1> ; 10/01/2022 24456 <1> ;jc short itrunc_0 ; error code in eax 24457 00004D86 5E <1> pop esi ; * ; 10/01/2022 24458 00004D87 31C0 <1> xor eax, eax ; 0 24459 00004D89 8946FC <1> mov [esi-4], eax ; 0 24460 <1> itrunc_3: 24461 00004D8C 81FE[58680000] <1> cmp esi, i.dskp+40 24462 00004D92 72E7 <1> jb short itrunc_2 ; next disk address ptr 24463 <1> itrunc_4: 24464 00004D94 A3[2C680000] <1> mov [i.size], eax ; 0 24465 <1> ;mov [i.size_h], al ; 0 24466 <1> 24467 <1> ; clear large file flag 24468 <1> ;and byte [i.flgs+1], 0EFh ; 11101111b ; not 10h 24469 <1> 24470 <1> ;call setimod 24471 <1> ;retn 24472 00004D99 E968FFFFFF <1> jmp setimod 24473 <1> 24474 <1> itrunc_5: 24475 <1> ; free disk blocks by using triple indirect blocks at first 24476 00004D9E BE[54680000] <1> mov esi, i.dskp+36 24477 00004DA3 8B06 <1> mov eax, [esi] 24478 00004DA5 09C0 <1> or eax, eax 24479 00004DA7 740C <1> jz short itrunc_6 24480 <1> 24481 00004DA9 BA02000000 <1> mov edx, 2 ; Triple indirect sign (level = 2) 24482 00004DAE E835000000 <1> call tloop 24483 <1> ; 10/01/2022 24484 <1> ;jc short itrunc_0 24485 <1> ; eax = 0 24486 00004DB3 8906 <1> mov [esi], eax ; 0 24487 <1> itrunc_6: 24488 <1> ; free disk blocks by using double indirect blocks at second 24489 00004DB5 BE[50680000] <1> mov esi, i.dskp+32 24490 00004DBA 8B06 <1> mov eax, [esi] 24491 00004DBC 21C0 <1> and eax, eax 24492 00004DBE 740C <1> jz short itrunc_7 24493 <1> 24494 00004DC0 BA01000000 <1> mov edx, 1 ; Double indirect sign (level = 1) 24495 00004DC5 E81E000000 <1> call tloop 24496 <1> ; 10/01/2022 24497 <1> ;jc short itrunc_0 24498 <1> ; eax = 0 24499 00004DCA 8906 <1> mov [esi], eax ; 0 24500 <1> ;esi = i.dskp+32 24501 <1> itrunc_7: 24502 <1> ; free disk blocks by using single indirect blocks at third 24503 00004DCC 83EE04 <1> sub esi, 4 24504 00004DCF 8B06 <1> mov eax, [esi] 24505 00004DD1 09C0 <1> or eax, eax 24506 00004DD3 7409 <1> jz short itrunc_8 24507 <1> 24508 00004DD5 29D2 <1> sub edx, edx ; 0 ; Single indirect sign (level = 0) 24509 00004DD7 E80C000000 <1> call tloop 24510 <1> ; 10/01/2022 24511 <1> ;jc short itrunc_0 24512 <1> ; eax = 0 24513 00004DDC 8906 <1> mov [esi], eax ; 0 24514 <1> itrunc_8: 24515 00004DDE 81FE[30680000] <1> cmp esi, i.dskp 24516 00004DE4 77E6 <1> ja short itrunc_7 24517 00004DE6 EBAC <1> jmp short itrunc_4 24518 <1> 24519 <1> tloop: 24520 <1> ; 26/03/2022 24521 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 24522 <1> ; 07/06/2020 24523 <1> ; 03/06/2020 24524 <1> ; 02/06/2020 24525 <1> ; 26/05/2020 - Retro UNIX 386 v2 by Erdogan Tan 24526 <1> ; 24527 <1> ; * Free all the disk blocks associated 24528 <1> ; * with the specified inode structure. 24529 <1> 24530 <1> ; Reference: 24531 <1> ; Retro UNIX 386 v2 FS installation utility 24532 <1> ; 17/01/2020 - 'UNIXHDCP.ASM', 'tloop' procedure 24533 <1> 24534 <1> ; INPUT: 24535 <1> ; 03/06/2020 24536 <1> ; eax = indirect block number/address (logical) 24537 <1> ; edx = level (in dl) 24538 <1> ; (0 = indirect, 1 = double indr. 2 = triple indr.) 24539 <1> ; 24540 <1> ; OUTPUT: 24541 <1> ; indirect blocks will be released 24542 <1> ; 24543 <1> ; Modified registers: eax, ebx, ecx, edx 24544 <1> 24545 <1> ; 03/06/2020 24546 <1> 24547 00004DE8 57 <1> push edi ; * 24548 00004DE9 56 <1> push esi ; ** 24549 <1> 24550 00004DEA 50 <1> push eax ; *** 24551 <1> 24552 00004DEB 52 <1> push edx ; **** level 24553 <1> 24554 <1> ; [ii] = current inode number 24555 <1> ;;[idev] = logical drive number of current inode, [ii] 24556 <1> ; eax = logical sector/block number 24557 <1> 24558 <1> ; 26/03/2022 24559 <1> ; [cdev] = logical drive number (0 or 1) 24560 <1> 24561 <1> ; 10/01/2022 24562 <1> ; convert to physical sector/block number/address 24563 00004DEC E856FAFFFF <1> call mget_2 24564 <1> 24565 00004DF1 E89A0B0000 <1> call dskrd ; read disk sector 24566 <1> 24567 <1> ;; ebx = buffer header address 24568 <1> ;; eax = physical sector/block number 24569 <1> ;; [pdn] = phsysical drive (index) number 24570 <1> 24571 <1> ;; Modified registers: eax, edx, ecx, esi, edi 24572 <1> ;; If cf = 1 --> eax = error code (al) 24573 <1> 24574 <1> ; 10/01/2022 24575 <1> ; Return from 'dskrd': (Retro UNIX 386 v1.2) 24576 <1> ; eax = physical block/sector number 24577 <1> ; ebx = buffer data address 24578 <1> ; Modified registers: edx, ecx, ebx, esi, edi, ebp 24579 <1> 24580 00004DF6 5A <1> pop edx ; **** ; level in dl 24581 <1> ; 10/01/2022 24582 <1> ;jc short tloop_5 24583 <1> 24584 <1> ;mov esi, [ebx+bufhdr.address] ; buffer address 24585 <1> ; 10/01/2022 24586 00004DF7 89DE <1> mov esi, ebx ; buffer data address 24587 <1> 24588 <1> ; 07/06/2020 24589 00004DF9 B980000000 <1> mov ecx, 512/4 ; 128 dwords 24590 <1> 24591 00004DFE 80FA01 <1> cmp dl, 1 ; - 24592 00004E01 722C <1> jb short tloop_7 24593 00004E03 7407 <1> je short tloop_1 24594 00004E05 BF[64750000] <1> mov edi, trpi_buf ; triple indirect buffer address 24595 00004E0A EB05 <1> jmp short tloop_2 24596 <1> tloop_1: 24597 00004E0C BF[64730000] <1> mov edi, dbli_buf ; double indirect buffer address 24598 <1> tloop_2: 24599 <1> ; copy disk r/w buffer content to indirect block buffer 24600 <1> ;mov ecx, 512/4 ; 128 dwords 24601 00004E11 F3A5 <1> rep movsd 24602 <1> 24603 00004E13 FECA <1> dec dl ; - 24604 <1> ; next indirect block level, 2 -> 1, 1 -> 0 24605 00004E15 89FE <1> mov esi, edi ; (dbli, trpi) indirect buffer + 512 24606 00004E17 B180 <1> mov cl, 128 ; 128 dwords 24607 <1> tloop_3: 24608 00004E19 83EE04 <1> sub esi, 4 ; previous pointer 24609 <1> 24610 00004E1C 8B06 <1> mov eax, [esi] 24611 <1> 24612 00004E1E 09C0 <1> or eax, eax ; 0 24613 00004E20 7409 <1> jz short tloop_4 24614 <1> 24615 <1> ; 26/03/2022 24616 00004E22 52 <1> push edx ; @@ 24617 <1> ; 03/06/2020 24618 00004E23 51 <1> push ecx ; @ 24619 00004E24 E8BFFFFFFF <1> call tloop 24620 00004E29 59 <1> pop ecx ; @ 24621 <1> ; 26/03/2022 24622 00004E2A 5A <1> pop edx ; @@ 24623 <1> ; 10/01/2022 24624 <1> ;jc short tloop_5 24625 <1> tloop_4: 24626 00004E2B E2EC <1> loop tloop_3 24627 <1> 24628 00004E2D EB1A <1> jmp short tloop_10 24629 <1> 24630 <1> ; 10/01/2022 24631 <1> ;tloop_5: 24632 <1> ; pop edx ; *** ; discard eax 24633 <1> ; ; error code in eax 24634 <1> ;tloop_6: 24635 <1> ; pop esi ; ** 24636 <1> ; pop edi ; * 24637 <1> ; retn 24638 <1> 24639 <1> ; free blocks in current indirect block 24640 <1> tloop_7: 24641 <1> ;mov ecx, 512/4 ; 128 dwords 24642 00004E2F 81C6FC010000 <1> add esi, 508 24643 <1> tloop_8: 24644 00004E35 8B06 <1> mov eax, [esi] 24645 00004E37 21C0 <1> and eax, eax ; 0 ? 24646 00004E39 7409 <1> jz short tloop_9 24647 <1> 24648 00004E3B 56 <1> push esi ; **** ; 10/01/2022 24649 00004E3C 51 <1> push ecx ; ***** 24650 00004E3D E881FCFFFF <1> call free 24651 <1> ; if cf = 0 -> eax = 0 24652 <1> ; if cf = 1 -> eax = error code (in al) 24653 00004E42 59 <1> pop ecx ; ***** 24654 00004E43 5E <1> pop esi ; **** ; 10/01/2022 24655 <1> ; 10/01/2022 24656 <1> ;; 07/06/2020 24657 <1> ;jc short tloop_6 24658 <1> tloop_9: 24659 00004E44 83EE04 <1> sub esi, 4 24660 00004E47 E2EC <1> loop tloop_8 24661 <1> tloop_10: 24662 00004E49 58 <1> pop eax ; *** ; free indirect block's itself 24663 00004E4A E874FCFFFF <1> call free 24664 <1> ;; if cf = 0 -> eax = 0 24665 <1> ;; if cf = 1 -> eax = error code (in al) 24666 <1> ; 10/01/2022 24667 <1> ; (if we are here, there is not an error, cf=0) 24668 <1> ;jmp short tloop_6 24669 <1> 24670 <1> ; 10/02/2022 24671 00004E4F 31C0 <1> xor eax, eax ; 0 24672 00004E51 5E <1> pop esi ; ** 24673 00004E52 5F <1> pop edi ; * 24674 00004E53 C3 <1> retn 24675 <1> 24676 <1> ; Retro UNIX 386 v2.0 'imap' code 24677 <1> ; (runix v2 fs inode map) 24678 <1> imap: 24679 <1> ; 18/04/2022 24680 <1> ; 26/03/2022 24681 <1> ; 12/03/2022 24682 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 24683 <1> ; (major modification) 24684 <1> ; 05/11/2021 - temporary (simplified code) 24685 <1> ; 21/08/2021 24686 <1> ; 15/08/2021 24687 <1> ; 14/06/2021 24688 <1> ; 02/05/2021 24689 <1> ; 01/04/2021, 08/04/2021, 24/04/2021 24690 <1> ; 29/03/2021 24691 <1> ; 28/03/2021 - Retro UNIX 386 v2 (beginning) 24692 <1> ; 24693 <1> ; 'imap' finds the byte in inode map containing 24694 <1> ; allocation bit for an i-node whose number in (E)AX 24695 <1> ; 24696 <1> ; (ref: 'UNIXHDCP.ASM', imap', 22/01/2020) 24697 <1> ; 24698 <1> ; ((Retro UNIX 386 v2 'imap' code is mostly different 24699 <1> ; than Retro UNIX 386 v1.1 'imap' code.)) 24700 <1> ; 24701 <1> ; INPUTS -> 24702 <1> ; EAX = inode number 24703 <1> ; 0 = first free inode 24704 <1> ; >0 = requested inode 24705 <1> ; [cdev] = current (logical) drive/device 24706 <1> ; 24707 <1> ; OUTPUTS -> 24708 <1> ; EBX = address of the byte contains allocation bit 24709 <1> ; DX has 1 at calculated bit position 24710 <1> ; ; 05/11/2021 24711 <1> ; EBP = superblock buffer address 24712 <1> ; (EAX = inode number) 24713 <1> ; 12/03/2022 24714 <1> ; (if EAX input is 0, EAX = first free inode > 1) 24715 <1> ; 24716 <1> ; ; 08/04/2021 24717 <1> ; If cf=1 -> error code in eax (al) 24718 <1> ; 24719 <1> ; Modified registers: ebx, ecx, edx, esi, edi, ebp 24720 <1> 24721 <1> ; 05/11/2021 24722 00004E54 803D[816C0000]00 <1> cmp byte [cdev], 0 24723 00004E5B 7616 <1> jna short imap_0 24724 <1> ; 10/01/2022 24725 00004E5D BD[5C6F0000] <1> mov ebp, mount ; mounted fs superblock buffer 24726 00004E62 EB14 <1> jmp short imap_1 24727 <1> 24728 <1> imap_ialloc_err: 24729 <1> ; 10/01/2022 24730 00004E64 C705[186D0000]2100- <1> mov dword [u.error], ERR_INO_ALLOC ; 33 24731 00004E6C 0000 <1> 24732 <1> ; 'inode allocation error !' 24733 00004E6E E9F2E2FFFF <1> jmp error 24734 <1> 24735 <1> imap_0: 24736 <1> ; 10/01/2022 24737 00004E73 BD[546D0000] <1> mov ebp, systm ; root fs superblock buffer 24738 <1> imap_1: 24739 <1> ; 26/03/2022 24740 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 24741 <1> imap_x: 24742 <1> ; 05/11/2021 24743 <1> ; 21/08/2021 24744 <1> ; 15/08/2021 (Retro UNIX 386 v2) 24745 <1> ; call from 'maknod2' ; 10/01/2022 24746 <1> ; 24747 <1> ; eax = inode number 24748 <1> ; [cdev] = device number for inode in eax 24749 <1> ; ebp = superblock buffer address 24750 <1> 24751 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 24752 <1> ; 'imap' and 'imap_x' will return with.. 24753 <1> ; ECX = byte offset from inode map buff (imap_x) 24754 <1> ; EBX = byte addr of the byte with allocation bit 24755 <1> ; EDX (DL) has a 1 in the calculated bit position 24756 <1> 24757 <1> ; 02/05/2021 24758 <1> ; convert inode number to first free inode if it is 0 24759 00004E78 E83B000000 <1> call imap_3 ; 10/01/2022 24760 00004E7D 72E5 <1> jc short imap_ialloc_err 24761 <1> ; eax = inode number > 1 (1 = root directory inode) 24762 <1> 24763 00004E7F 898584000000 <1> mov [ebp+SB.LastInode], eax 24764 <1> 24765 00004E85 50 <1> push eax ; * ; save inode number 24766 <1> 24767 <1> ; convert inode number to inode map sector index 24768 00004E86 E845000000 <1> call imap_8 ; 10/01/2022 24769 00004E8B 50 <1> push eax ; ** ; byte offset in inode map buffer 24770 <1> 24771 <1> ; edx = inode map buffer sector index number (< 16) 24772 <1> ; eax = byte offset in inode map buffer (< 512) 24773 <1> 24774 <1> ; 15/08/2021 24775 00004E8C 89958C000000 <1> mov [ebp+SB.ImapIndex], edx 24776 00004E92 8B4520 <1> mov eax, [ebp+SB.InodeMapAddr] 24777 00004E95 01D0 <1> add eax, edx 24778 00004E97 034504 <1> add eax, [ebp+SB.BootSectAddr] 24779 <1> ; eax = physical sector number 24780 <1> ; [cdev] = current device/disk number 24781 <1> 24782 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 24783 00004E9A 55 <1> push ebp ; *** 24784 00004E9B E8F00A0000 <1> call dskrd 24785 00004EA0 5D <1> pop ebp ; *** 24786 <1> ; cpu returns here if there is/was not an error in 'dskrd' 24787 <1> ; eax = physical sector number 24788 <1> ; ebx = buffer data address 24789 <1> 24790 <1> ; 26/03/2022 24791 <1> ; (ecx may be > 255 at return from dskrd) 24792 <1> ;sub ecx, ecx ; 0 24793 <1> ; 10/01/2022 24794 <1> ;mov cl, [esp+4] ; * ; inode number 24795 <1> ; 18/04/2022 24796 00004EA1 8B4C2404 <1> mov ecx, [esp+4] ; * ; inode number 24797 00004EA5 FEC9 <1> dec cl 24798 <1> ; 26/03/2022 24799 00004EA7 31D2 <1> xor edx, edx 24800 <1> ;mov dl, 1 24801 00004EA9 FEC2 <1> inc dl ; dl = 1 24802 <1> ;and ecx, 7 24803 <1> ; 26/03/2022 24804 <1> ; 02/05/2021 24805 <1> ;dec cl 24806 <1> ;jz short imap_2 ; 15/08/2021 24807 00004EAB 80E107 <1> and cl, 7 ; 1 imap byte is for 8 inodes 24808 <1> ;jz short imap_2 24809 00004EAE D2E2 <1> shl dl, cl 24810 <1> imap_2: 24811 <1> ; 10/01/2022 24812 <1> ; save physical sector number of imap sector in the SB 24813 00004EB0 89457C <1> mov [ebp+SB.ImapBuffer], eax ; ! sector addr ! 24814 <1> ; 24815 00004EB3 59 <1> pop ecx ; ** ; byte offset in inode map buffer 24816 00004EB4 01CB <1> add ebx, ecx ; + byte position 24817 00004EB6 58 <1> pop eax ; * ; inode number 24818 <1> 24819 <1> ; 10/01/2022 24820 <1> ; ECX contains byte offset from inode map buff (imap_x) 24821 <1> ; EDX (DL) has a 1 in the calculated bit position 24822 <1> ; EBX has byte address of the byte with allocation bit 24823 <1> 24824 00004EB7 C3 <1> retn 24825 <1> 24826 <1> imap_3: 24827 <1> ; 10/01/2022 24828 <1> ; 15/08/2021 24829 <1> ; 02/05/2021 24830 <1> ; 28/03/2021 24831 <1> ; get first free inode number (from superblock) 24832 <1> ; and check inode number against inode count 24833 <1> ; 24834 <1> ; INPUT: 24835 <1> ; eax = 0 -> get first free inode number 24836 <1> ; (eax > 0 -> check inode number) 24837 <1> ; ebp = superblock address ; 15/08/2021 24838 <1> ; OUTPUT: 24839 <1> ; eax = inode number 24840 <1> ; (eax will be 2 when SB.FirstFreeIno is invalid) 24841 <1> ; cf = 1 -> inode allocation error/problem 24842 <1> 24843 00004EB8 21C0 <1> and eax, eax 24844 00004EBA 750E <1> jnz short imap_5 24845 <1> 24846 <1> ; get first free inode 24847 <1> ;mov eax, [ebp+SB.FreeInodes] 24848 <1> ;and eax, eax 24849 <1> ;jz short imap_6 24850 <1> ; 10/01/2022 24851 00004EBC 394530 <1> cmp [ebp+SB.FreeInodes], eax ; 0 24852 00004EBF 760D <1> jna short imap_6 24853 00004EC1 8B4534 <1> mov eax, [ebp+SB.FirstFreeIno] ; 1 based inode num 24854 00004EC4 40 <1> inc eax 24855 00004EC5 7502 <1> jnz short imap_4 ; 0FFFFFFFFh -> 0 24856 <1> ; invalid first free inode value (not initialized) 24857 00004EC7 B003 <1> mov al, 3 ; first free inode to be searched + 1 24858 <1> imap_4: 24859 00004EC9 48 <1> dec eax 24860 <1> imap_5: 24861 <1> ; 15/08/2021 24862 <1> ; check inode number against inode count of the fs 24863 00004ECA 394514 <1> cmp [ebp+SB.InodeCount], eax 24864 00004ECD C3 <1> retn ; if cf = 1 --> inode number > inode count 24865 <1> imap_6: 24866 <1> ; 'imap' inode allocation error ! 24867 00004ECE F9 <1> stc 24868 <1> imap_7: 24869 00004ECF C3 <1> retn 24870 <1> 24871 <1> imap_8: 24872 <1> ; 10/01/2022 24873 <1> ; 15/08/2021 24874 <1> ; 02/05/2021 24875 <1> ; 28/03/2021 24876 <1> ; convert inode count to inode map sector index 24877 <1> ; 24878 <1> ; INPUT: 24879 <1> ; eax = inode number 24880 <1> ; OUTPUT: 24881 <1> ; edx = inode map sector offset/index number 24882 <1> ; eax = byte offset from start of imapbuf 24883 <1> 24884 00004ED0 31D2 <1> xor edx, edx 24885 00004ED2 48 <1> dec eax ; zero based inode number 24886 00004ED3 74FA <1> jz short imap_7 24887 <1> 24888 00004ED5 C1E803 <1> shr eax, 3 ; 8 inodes per inode map byte 24889 <1> ; eax = byte offset from start of inode map 24890 00004ED8 88E2 <1> mov dl, ah ; ah <= 31 (1Fh) for Retro UNIX 386 v2 24891 00004EDA D0EA <1> shr dl, 1 24892 <1> ; edx = inode map sector offset/index number 24893 <1> ;and eax, 511 24894 00004EDC 6625FF01 <1> and ax, 511 24895 <1> ; eax = byte offset from start of imapbuf 24896 00004EE0 C3 <1> retn 24897 %include 'u6.s' ; 31/05/2015 24898 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 24899 <1> ; (re-write kernel for test by using previous version without a major defect) 24900 <1> ; **************************************************************************** 24901 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.3) - SYS6.INC 24902 <1> ; Last Modification: 19/07/2022 24903 <1> ; ---------------------------------------------------------------------------- 24904 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 24905 <1> ; (v0.1 - Beginning: 11/07/2012) 24906 <1> ; 24907 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 24908 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 24909 <1> ; 24910 <1> ; 24911 <1> ; 24912 <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s 24913 <1> ; 24914 <1> ; **************************************************************************** 24915 <1> 24916 <1> ; 09/03/2022 24917 <1> ; 25/12/2021 24918 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 24919 <1> readi: 24920 <1> ; 20/05/2015 24921 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 24922 <1> ; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 24923 <1> ; 24924 <1> ; Reads from an inode whose number in R1 24925 <1> ; 24926 <1> ; INPUTS -> 24927 <1> ; r1 - inode number 24928 <1> ; u.count - byte count user desires 24929 <1> ; u.base - points to user buffer 24930 <1> ; u.fofp - points to word with current file offset 24931 <1> ; OUTPUTS -> 24932 <1> ; u.count - cleared 24933 <1> ; u.nread - accumulates total bytes passed back 24934 <1> ; 24935 <1> ; ((AX = R1)) input/output 24936 <1> ; (Retro UNIX Prototype: 01/03/2013 - 14/12/2012, UNIXCOPY.ASM) 24937 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi)) -15/07/2022- 24938 <1> 24939 00004EE1 31D2 <1> xor edx, edx ; 0 24940 00004EE3 8915[D06C0000] <1> mov [u.nread], edx ; 0 24941 <1> ; clr u.nread / accumulates number of bytes transmitted 24942 00004EE9 668915[106D0000] <1> mov [u.pcount], dx ; 19/05/2015 24943 00004EF0 3915[CC6C0000] <1> cmp [u.count], edx ; 0 24944 <1> ; tst u.count / is number of bytes to be read greater than 0 24945 00004EF6 7701 <1> ja short readi_1 ; 1f 24946 <1> ; bgt 1f / yes, branch 24947 00004EF8 C3 <1> retn 24948 <1> ; rts r0 / no, nothing to read; return to caller 24949 <1> readi_1: ; 1: 24950 <1> ; ; mov r1,-(sp) / save i-number on stack 24951 <1> ;cmp ax, 40 24952 <1> ; ; cmp r1,$40. / want to read a special file 24953 <1> ; ; / (i-nodes 1,...,40 are for special files) 24954 <1> ;ja dskr 24955 <1> ; ; ble 1f / yes, branch 24956 <1> ; ; jmp dskr / no, jmp to dskr; 24957 <1> ; ; / read file with i-node number (r1) 24958 <1> ; ; / starting at byte ((u.fofp)), read in u.count bytes 24959 <1> 24960 <1> ; 28/11/2021 24961 00004EF9 F605[166D0000]FF <1> test byte [u.kcall], 0FFh 24962 <1> ;jnz short readi_2 ; 'readi' called by 'namei' 24963 <1> ; 09/03/2022 24964 <1> ;jz short _readi_2 24965 <1> ;jmp dskr 24966 00004F00 750C <1> jnz short readi_2 ; 'readi' called by 'namei' 24967 <1> ;_readi_2: ; 09/03/2022 24968 <1> ; eax = inode number 24969 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 24970 00004F02 E86EFCFFFF <1> call iget 24971 <1> ;readi_2: 24972 <1> ; 28/11/2021 24973 <1> ; eax = inode number 24974 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 24975 00004F07 E800050000 <1> call is_regular_file 24976 <1> ;jz dskr ; regular file 24977 <1> ; 25/12/2021 24978 00004F0C 7505 <1> jnz short readi_5 ; device file 24979 <1> readi_2: ; 09/03/2022 24980 <1> ; regular file 24981 00004F0E E9E3000000 <1> jmp dskr 24982 <1> readi_5: 24983 <1> ; (20/05/2015) 24984 00004F13 50 <1> push eax ; because subroutines will jump to 'ret_' 24985 <1> 24986 <1> ; 28/11/2021 24987 <1> ; device file 24988 00004F14 BB[2E4F0000] <1> mov ebx, readi_4 24989 00004F19 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 24990 00004F1C 720E <1> jb short readi_3 24991 00004F1E 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 24992 00004F21 7709 <1> ja short readi_3 24993 <1> 24994 <1> ; convert v2 inode number to v1 device inode number 24995 00004F23 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 24996 00004F25 89C1 <1> mov ecx, eax 24997 00004F27 C0E102 <1> shl cl, 2 ; * 4 24998 00004F2A 01CB <1> add ebx, ecx 24999 <1> readi_3: 25000 00004F2C FF23 <1> jmp dword [ebx] 25001 <1> ; jmp *1f-2(r1) 25002 <1> readi_4: ; 1: 25003 00004F2E [7E4F0000] <1> dd null ; 28/11/2021 25004 00004F32 [824F0000] <1> dd rtty ; tty, AX = 1 (runix) 25005 <1> ;rtty / tty; r1=2 25006 <1> ;rppt / ppt; r1=4 25007 00004F36 [D24F0000] <1> dd rmem ; mem, AX = 2 (runix) 25008 <1> ;rmem / mem; r1=6 25009 <1> ;rrf0 / rf0 25010 <1> ;rrk0 / rk0 25011 <1> ;rtap / tap0 25012 <1> ;rtap / tap1 25013 <1> ;rtap / tap2 25014 <1> ;rtap / tap3 25015 <1> ;rtap / tap4 25016 <1> ;rtap / tap5 25017 <1> ;rtap / tap6 25018 <1> ;rtap / tap7 25019 00004F3A [51580000] <1> dd rfd ; fd0, AX = 3 (runix only) 25020 00004F3E [51580000] <1> dd rfd ; fd1, AX = 4 (runix only) 25021 00004F42 [51580000] <1> dd rhd ; hd0, AX = 5 (runix only) 25022 00004F46 [51580000] <1> dd rhd ; hd1, AX = 6 (runix only) 25023 00004F4A [51580000] <1> dd rhd ; hd2, AX = 7 (runix only) 25024 00004F4E [51580000] <1> dd rhd ; hd3, AX = 8 (runix only) 25025 00004F52 [E74F0000] <1> dd rlpr ; lpr, AX = 9 (invalid, write only device !?) 25026 00004F56 [CE4F0000] <1> dd rcvt ; tty0, AX = 10 (runix) 25027 <1> ;rcvt / tty0 25028 00004F5A [CE4F0000] <1> dd rcvt ; tty1, AX = 11 (runix) 25029 <1> ;rcvt / tty1 25030 00004F5E [CE4F0000] <1> dd rcvt ; tty2, AX = 12 (runix) 25031 <1> ;rcvt / tty2 25032 00004F62 [CE4F0000] <1> dd rcvt ; tty3, AX = 13 (runix) 25033 <1> ;rcvt / tty3 25034 00004F66 [CE4F0000] <1> dd rcvt ; tty4, AX = 14 (runix) 25035 <1> ;rcvt / tty4 25036 00004F6A [CE4F0000] <1> dd rcvt ; tty5, AX = 15 (runix) 25037 <1> ;rcvt / tty5 25038 00004F6E [CE4F0000] <1> dd rcvt ; tty6, AX = 16 (runix) 25039 <1> ;rcvt / tty6 25040 00004F72 [CE4F0000] <1> dd rcvt ; tty7, AX = 17 (runix) 25041 <1> ;rcvt / tty7 25042 00004F76 [CE4F0000] <1> dd rcvt ; COM1, AX = 18 (runix only) 25043 <1> ;rcrd / crd 25044 00004F7A [CE4F0000] <1> dd rcvt ; COM2, AX = 19 (runix only) 25045 <1> 25046 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 25047 <1> null: 25048 00004F7E 31C0 <1> xor eax, eax 25049 00004F80 58 <1> pop eax 25050 00004F81 C3 <1> retn 25051 <1> 25052 <1> ; 11/01/2022 25053 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 25054 <1> rtty: ; / read from console tty 25055 <1> ; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1) 25056 <1> ; (Only 1 byte is read, by ignoring byte count!) 25057 <1> ; WHAT FOR: Every character from Keyboard input 25058 <1> ; must be written immediate on video page (screen) 25059 <1> ; when it is required. 25060 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25061 <1> ; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1) 25062 <1> ; 25063 <1> ; Console tty buffer is PC keyboard buffer 25064 <1> ; and keyboard-keystroke handling is different than original 25065 <1> ; unix (PDP-11) here. TTY/Keyboard procedures here are changed 25066 <1> ; according to IBM PC compatible ROM BIOS keyboard functions. 25067 <1> ; 25068 <1> ; 06/12/2013 25069 00004F82 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 25070 00004F89 8A83[A3680000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 25071 <1> rttys: 25072 <1> ; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of 25073 <1> ; / of the control and status block 25074 <1> ; tst 2(r5) / for the console tty; this word points to the console 25075 <1> ; / tty buffer 25076 <1> ; 28/07/2013 25077 00004F8F A2[D96C0000] <1> mov [u.ttyn], al 25078 <1> ; 13/01/2014 25079 00004F94 FEC0 <1> inc al 25080 00004F96 A2[DA6C0000] <1> mov [u.ttyp], al ; tty number + 1 25081 <1> rtty_nc: ; 01/02/2014 25082 <1> ; 29/09/2013 25083 <1> ;mov ecx, 10 25084 <1> ; 11/01/2022 25085 00004F9B 29C9 <1> sub ecx, ecx 25086 00004F9D B10A <1> mov cl, 10 25087 <1> rtty_1: ; 01/02/2014 25088 <1> ;push cx ; 29/09/2013 25089 <1> ; 11/12/2021 25090 00004F9F 51 <1> push ecx 25091 <1> ; byte [u.ttyn] = tty number (0 to 9) 25092 00004FA0 B001 <1> mov al, 1 25093 00004FA2 E8C20B0000 <1> call getc 25094 <1> ;pop cx ; 29/09/2013 25095 <1> ; 11/12/2021 25096 00004FA7 59 <1> pop ecx 25097 00004FA8 7516 <1> jnz short rtty_2 25098 <1> ; bne 1f / 2nd word of console tty buffer contains number 25099 <1> ; / of chars. Is this number non-zero? 25100 00004FAA E20D <1> loop rtty_idle ; 01/02/2014 25101 <1> ; 05/10/2013 25102 00004FAC 8A25[D96C0000] <1> mov ah, [u.ttyn] 25103 <1> ; 29/09/2013 25104 00004FB2 E8C9F7FFFF <1> call sleep 25105 <1> ; jsr r0,canon; ttych / if 0, call 'canon' to get a line 25106 <1> ; / (120 chars.) 25107 <1> ; byte [u.ttyn] = tty number (0 to 9) 25108 00004FB7 EBE2 <1> jmp short rtty_nc ; 01/02/2014 25109 <1> 25110 <1> rtty_idle: 25111 <1> ; 29/07/2013 25112 00004FB9 E835F7FFFF <1> call idle 25113 00004FBE EBDF <1> jmp short rtty_1 ; 01/02/2014 25114 <1> ;1: 25115 <1> ; tst 2(r5) / is the number of characters zero 25116 <1> ; beq ret1 / yes, return to caller via 'ret1' 25117 <1> ; movb *4(r5),r1 / no, put character in r1 25118 <1> ; inc 4(r5) / 3rd word of console tty buffer points to byte which 25119 <1> ; / contains the next char. 25120 <1> ; dec 2(r5) / decrement the character count 25121 <1> rtty_2: 25122 00004FC0 30C0 <1> xor al, al 25123 00004FC2 E8A20B0000 <1> call getc 25124 00004FC7 E895000000 <1> call passc 25125 <1> ; jsr r0,passc / move the character to core (user) 25126 <1> ;; 17/10/2015 - 16/07/2015 25127 <1> ; 19/06/2014 25128 <1> ;;jnz short rtty_nc 25129 00004FCC 58 <1> pop eax ; (20/05/2015) 25130 00004FCD C3 <1> retn 25131 <1> ;ret1: 25132 <1> ; jmp ret / return to caller via 'ret' 25133 <1> 25134 <1> rcvt: ; < receive/read character from tty > 25135 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25136 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 25137 <1> ; 25138 <1> ; Retro UNIX 8086 v1 modification ! 25139 <1> ; 25140 <1> ; In original UNIX v1, 'rcvt' routine 25141 <1> ; (exactly different than this one) 25142 <1> ; was in 'u9.s' file. 25143 <1> ; 25144 00004FCE 2C0A <1> sub al, 10 25145 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 25146 <1> ; 16/07/2013 25147 <1> ; 21/05/2013 25148 00004FD0 EBBD <1> jmp short rttys 25149 <1> 25150 <1> ;rppt: / read paper tape 25151 <1> ; jsr r0,pptic / gets next character in clist for ppt input and 25152 <1> ; / places 25153 <1> ; br ret / it in r1; if there 1s no problem with reader, it 25154 <1> ; / also enables read bit in prs 25155 <1> ; jsr r0,passc / place character in users buffer area 25156 <1> ; br rppt 25157 <1> 25158 <1> rmem: ; / transfer characters from memory to a user area of core 25159 <1> ; 17/10/2015 25160 <1> ; 11/06/2015 25161 <1> ; 24/05/2015 25162 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25163 <1> ; 25164 00004FD2 8B35[B86C0000] <1> mov esi, [u.fofp] 25165 <1> rmem_1: 25166 00004FD8 8B1E <1> mov ebx, [esi] 25167 <1> ; mov *u.fofp,r1 / save file offset which points to the char 25168 <1> ; / to be transferred to user 25169 00004FDA FF06 <1> inc dword [esi] ; 17/10/2015 25170 <1> ; inc *u.fofp / increment file offset to point to 'next' 25171 <1> ; / char in memory file 25172 00004FDC 8A03 <1> mov al, [ebx] 25173 <1> ; movb (r1),r1 / get character from memory file, 25174 <1> ; / put it in r1 25175 00004FDE E87E000000 <1> call passc ; jsr r0,passc / move this character to 25176 <1> ; / the next byte of the users core area 25177 <1> ; br rmem / continue 25178 00004FE3 75F3 <1> jnz short rmem_1 25179 <1> ret_: 25180 00004FE5 58 <1> pop eax ; 09/06/2015 25181 00004FE6 C3 <1> retn 25182 <1> 25183 <1> rlpr: 25184 <1> ;1: 25185 <1> ;rcrd: 25186 00004FE7 C705[186D0000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 25187 00004FEF 0000 <1> 25188 00004FF1 E96FE1FFFF <1> jmp error 25189 <1> ;jmp error / see 'error' routine 25190 <1> 25191 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 25192 <1> dskr: 25193 <1> ; 19/07/2022 25194 <1> ; 12/10/2015 25195 <1> ; 21/08/2015 25196 <1> ; 25/07/2015 25197 <1> ; 10/07/2015 25198 <1> ; 16/06/2015 25199 <1> ; 31/05/2015 25200 <1> ; 24/05/2015 (Retro UNIX 386 v1 - Beginning) 25201 <1> ; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 25202 <1> dskr_0: 25203 00004FF6 50 <1> push eax 25204 <1> ; mov (sp),r1 / i-number in r1 25205 <1> ; AX = i-number 25206 00004FF7 E879FBFFFF <1> call iget 25207 <1> ; jsr r0,iget / get i-node (r1) into i-node section of core 25208 <1> ;movzx edx, word [i.size] ; 16/06/2015 25209 <1> ; ; mov i.size,r2 / file size in bytes in r2 25210 <1> ; 28/11/2021 25211 00004FFC 8B15[2C680000] <1> mov edx, [i.size] ; 32 bit file size (runix v2 inode) 25212 <1> ; 25213 00005002 8B1D[B86C0000] <1> mov ebx, [u.fofp] 25214 00005008 2B13 <1> sub edx, [ebx] 25215 <1> ; sub *u.fofp,r2 / subtract file offset 25216 <1> ; 12/10/2015 25217 <1> ; jna short ret_ 25218 <1> ; blos ret 25219 0000500A 7709 <1> ja short dskr_1 25220 <1> ; 25221 <1> dskr_retn: ; 12/10/2015 25222 0000500C 58 <1> pop eax 25223 0000500D C605[166D0000]00 <1> mov byte [u.kcall], 0 25224 00005014 C3 <1> retn 25225 <1> dskr_1: 25226 00005015 3B15[CC6C0000] <1> cmp edx, [u.count] 25227 <1> ; cmp r2,u.count / are enough bytes left in file 25228 <1> ; / to carry out read 25229 0000501B 7306 <1> jnb short dskr_2 25230 <1> ; bhis 1f 25231 0000501D 8915[CC6C0000] <1> mov [u.count], edx 25232 <1> ; mov r2,u.count / no, just read to end of file 25233 <1> dskr_2: ; 1: 25234 <1> ; (E)AX = i-number ; 28/11/2021 (32 bit inode number) 25235 <1> ;call mget 25236 <1> ; jsr r0,mget / returns physical block number of block 25237 <1> ; / in file where offset points 25238 <1> ; 28/11/2021 25239 00005023 E8D9F7FFFF <1> call mget_r 25240 <1> 25241 <1> ; eax = physical block number 25242 <1> ; [cdev] = current device number 25243 00005028 E863090000 <1> call dskrd 25244 <1> ; jsr r0,dskrd / read in block, r5 points to 25245 <1> ; / 1st word of data in buffer 25246 <1> ; 09/06/2015 25247 0000502D 803D[166D0000]00 <1> cmp byte [u.kcall], 0 ; the caller is 'namei' sign (=1) 25248 00005034 770F <1> ja short dskr_4 ; zf=0 -> the caller is 'namei' 25249 00005036 66833D[106D0000]00 <1> cmp word [u.pcount], 0 25250 0000503E 7705 <1> ja short dskr_4 25251 <1> dskr_3: 25252 <1> ; [u.base] = virtual address to transfer (as destination address) 25253 00005040 E857000000 <1> call trans_addr_w ; translate virtual address to physical (w) 25254 <1> dskr_4: 25255 <1> ; EBX (r5) = system (I/O) buffer address -physical- 25256 00005045 E843030000 <1> call sioreg 25257 <1> ; jsr r0,sioreg 25258 <1> 25259 <1> ; 19/07/2022 25260 <1> ;xchg esi, edi 25261 <1> 25262 <1> ; 19/07/2022 25263 <1> ; EDX = user data offset (previous value of [u.pbase]) 25264 <1> ; ESI = pointer to file offset 25265 <1> ; EDI = system (I/O) buffer offset 25266 <1> ; ECX = byte count 25267 <1> ; EBX = system buffer (data) address 25268 <1> ; EAX = remain bytes after byte count within page frame 25269 <1> 25270 0000504A 010E <1> add [esi], ecx 25271 <1> ; new file offset (old offset + byte count) 25272 <1> ; 25273 0000504C 89FE <1> mov esi, edi ; sector (I/O) buffer offset 25274 0000504E 89D7 <1> mov edi, edx 25275 <1> 25276 <1> ; EDI = file (user data) offset 25277 <1> ; ESI = sector (I/O) buffer offset 25278 <1> ; ECX = byte count 25279 00005050 F3A4 <1> rep movsb 25280 <1> ; movb (r2)+,(r1)+ / move data from buffer into working core 25281 <1> ; / starting at u.base 25282 <1> ; dec r3 25283 <1> ; bne 2b / branch until proper number of bytes are transferred 25284 <1> ; 25/07/2015 25285 <1> ; eax = remain bytes in buffer 25286 <1> ; (check if remain bytes in the buffer > [u.pcount]) 25287 00005052 09C0 <1> or eax, eax 25288 00005054 75EA <1> jnz short dskr_3 ; (page end before system buffer end!) 25289 <1> ; 03/08/2013 25290 <1> ;pop eax 25291 00005056 390D[CC6C0000] <1> cmp [u.count], ecx ; 0 25292 <1> ; tst u.count / all bytes read off disk 25293 <1> ; bne dskr 25294 <1> ; br ret 25295 <1> ;ja short dskr_0 25296 <1> ;mov [u.kcall], cl ; 0 ; 09/06/2015 25297 <1> ;retn 25298 <1> ; 12/10/2015 25299 0000505C 76AE <1> jna short dskr_retn 25300 0000505E 58 <1> pop eax ; (i-node number) 25301 0000505F EB95 <1> jmp short dskr_0 25302 <1> 25303 <1> passc: 25304 <1> ; 18/10/2015 25305 <1> ; 10/07/2015 25306 <1> ; 01/07/2015 25307 <1> ; 08/06/2015 25308 <1> ; 04/06/2015 25309 <1> ; 20/05/2015 25310 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25311 <1> ; 25312 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 25313 <1> ; to physical address 25314 00005061 66833D[106D0000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 25315 <1> ; 1-4095 --> use previous physical base address 25316 <1> ; in [u.pbase] 25317 00005069 7705 <1> ja short passc_3 25318 <1> ; 08/06/2015 - 10/07/2015 25319 0000506B E82C000000 <1> call trans_addr_w 25320 <1> passc_3: 25321 <1> ; 19/05/2015 25322 00005070 66FF0D[106D0000] <1> dec word [u.pcount] 25323 <1> ; 25324 00005077 8B1D[0C6D0000] <1> mov ebx, [u.pbase] 25325 0000507D 8803 <1> mov [ebx], al 25326 <1> ; movb r1,*u.base / move a character to the next byte of the 25327 <1> ; / users buffer 25328 0000507F FF05[C86C0000] <1> inc dword [u.base] 25329 <1> ; inc u.base / increment the pointer to point to 25330 <1> ; / the next byte in users buffer 25331 00005085 FF05[0C6D0000] <1> inc dword [u.pbase] ; 04/06/2015 25332 0000508B FF05[D06C0000] <1> inc dword [u.nread] 25333 <1> ; inc u.nread / increment the number of bytes read 25334 00005091 FF0D[CC6C0000] <1> dec dword [u.count] 25335 <1> ; dec u.count / decrement the number of bytes to be read 25336 <1> ; bne 1f / any more bytes to read? ; yes, branch 25337 00005097 C3 <1> retn 25338 <1> ; mov (sp)+,r0 / no, do a non-local return to the caller of 25339 <1> ; / 'readi' by: 25340 <1> ;/ (1) pop the return address off the stack into r0 25341 <1> ; mov (sp)+,r1 / (2) pop the i-number off the stack into r1 25342 <1> ;1: 25343 <1> ; clr *$ps / clear processor status 25344 <1> ; rts r0 / return to address currently on top of stack 25345 <1> 25346 <1> trans_addr_r: 25347 <1> ; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2) 25348 <1> ; -'add_to_swap_queue' call is disabled as temporary- 25349 <1> ; Translate virtual address to physical address 25350 <1> ; for reading from user's memory space 25351 <1> ; (Retro UNIX 386 v1 feature only !) 25352 <1> ; 18/10/2015 25353 <1> ; 10/07/2015 25354 <1> ; 09/06/2015 25355 <1> ; 08/06/2015 25356 <1> ; 04/06/2015 25357 <1> ; 25358 <1> ; 18/10/2015 25359 00005098 31D2 <1> xor edx, edx ; 0 (read access sign) 25360 0000509A EB04 <1> jmp short trans_addr_rw 25361 <1> 25362 <1> ;push eax 25363 <1> ;push ebx 25364 <1> ;mov ebx, [u.base] 25365 <1> ;call get_physical_addr ; get physical address 25366 <1> ;;jnc short cpass_0 25367 <1> ;jnc short passc_1 25368 <1> ;mov [u.error], eax 25369 <1> ;;pop ebx 25370 <1> ;;pop eax 25371 <1> ;jmp error 25372 <1> ;cpass_0: 25373 <1> ; 18/10/2015 25374 <1> ; 20/05/2015 25375 <1> ;mov [u.pbase], eax ; physical address 25376 <1> ;mov [u.pcount], cx ; remain byte count in page (1-4096) 25377 <1> ;pop ebx 25378 <1> ;pop eax 25379 <1> ;retn ; 08/06/2015 25380 <1> 25381 <1> trans_addr_w: 25382 <1> ; 31/12/2021 25383 <1> ; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2) 25384 <1> ; -'add_to_swap_queue' call is disabled as temporary- 25385 <1> ; Translate virtual address to physical address 25386 <1> ; for writing to user's memory space 25387 <1> ; (Retro UNIX 386 v1 feature only !) 25388 <1> ; 18/10/2015 25389 <1> ; 29/07/2015 25390 <1> ; 10/07/2015 25391 <1> ; 09/06/2015 25392 <1> ; 08/06/2015 25393 <1> ; 04/06/2015 (passc) 25394 <1> ; 25395 <1> ; 18/10/2015 25396 0000509C 29D2 <1> sub edx, edx 25397 0000509E FEC2 <1> inc dl ; 1 (write access sign) 25398 <1> trans_addr_rw: 25399 000050A0 50 <1> push eax 25400 000050A1 53 <1> push ebx 25401 <1> ; 18/10/2015 25402 000050A2 52 <1> push edx ; r/w sign (in DL) 25403 <1> ; 25404 000050A3 8B1D[C86C0000] <1> mov ebx, [u.base] 25405 000050A9 E819D7FFFF <1> call get_physical_addr ; get physical address 25406 000050AE 730A <1> jnc short passc_0 25407 000050B0 A3[186D0000] <1> mov [u.error], eax 25408 <1> ;pop edx 25409 <1> ;pop ebx 25410 <1> ;pop eax 25411 000050B5 E9ABE0FFFF <1> jmp error 25412 <1> passc_0: 25413 000050BA F6C202 <1> test dl, PTE_A_WRITE ; writable page ; 18/10/2015 25414 000050BD 5A <1> pop edx ; 18/10/2015 25415 000050BE 7517 <1> jnz short passc_1 25416 <1> ; 18/10/2015 25417 000050C0 20D2 <1> and dl, dl 25418 000050C2 7413 <1> jz short passc_1 25419 <1> ; 20/05/2015 25420 <1> ; read only (duplicated) page -must be copied to a new page- 25421 <1> ; EBX = linear address 25422 000050C4 51 <1> push ecx 25423 <1> ; 31/12/2021 - Retro UNIX 386 v1.2 (BugFix) 25424 000050C5 53 <1> push ebx ;* ; BugFix ; 31/12/2021 25425 000050C6 E86DD6FFFF <1> call copy_page 25426 000050CB 5B <1> pop ebx ;* ; BugFix ; 31/12/2021 25427 000050CC 59 <1> pop ecx 25428 000050CD 7217 <1> jc short passc_2 25429 <1> ; 30/11/2021 25430 <1> ;push eax ; physical address of the new/allocated page 25431 <1> ;call add_to_swap_queue 25432 <1> ;pop eax 25433 <1> ; 18/10/2015 25434 000050CF 81E3FF0F0000 <1> and ebx, PAGE_OFF ; 0FFFh 25435 <1> ;mov ecx, PAGE_SIZE 25436 <1> ;sub ecx, ebx 25437 000050D5 01D8 <1> add eax, ebx 25438 <1> passc_1: 25439 <1> ; 18/10/2015 25440 <1> ; 20/05/2015 25441 000050D7 A3[0C6D0000] <1> mov [u.pbase], eax ; physical address 25442 000050DC 66890D[106D0000] <1> mov [u.pcount], cx ; remain byte count in page (1-4096) 25443 000050E3 5B <1> pop ebx 25444 000050E4 58 <1> pop eax 25445 000050E5 C3 <1> retn ; 08/06/2015 25446 <1> passc_2: 25447 000050E6 C705[186D0000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error 25448 000050EE 0000 <1> 25449 <1> ;pop ebx 25450 <1> ;pop eax 25451 000050F0 E970E0FFFF <1> jmp error 25452 <1> 25453 <1> ; 09/03/2022 25454 <1> ; 25/12/2021 25455 <1> ; 11/12/2021 25456 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 25457 <1> writei: 25458 <1> ; 20/05/2015 25459 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25460 <1> ; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 25461 <1> ; 25462 <1> ; Write data to file with inode number in R1 25463 <1> ; 25464 <1> ; INPUTS -> 25465 <1> ; r1 - inode number 25466 <1> ; u.count - byte count to be written 25467 <1> ; u.base - points to user buffer 25468 <1> ; u.fofp - points to word with current file offset 25469 <1> ; OUTPUTS -> 25470 <1> ; u.count - cleared 25471 <1> ; u.nread - accumulates total bytes passed back 25472 <1> ; ((AX = R1)) 25473 <1> ; (Retro UNIX Prototype: 18/11/2012 - 11/11/2012, UNIXCOPY.ASM) 25474 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi)) -15/07/2022- 25475 <1> 25476 000050F5 31C9 <1> xor ecx, ecx 25477 000050F7 890D[D06C0000] <1> mov [u.nread], ecx ; 0 25478 <1> ; clr u.nread / clear the number of bytes transmitted during 25479 <1> ; / read or write calls 25480 000050FD 66890D[106D0000] <1> mov [u.pcount], cx ; 19/05/2015 25481 00005104 390D[CC6C0000] <1> cmp [u.count], ecx 25482 <1> ; ; tst u.count / test the byte count specified by the user 25483 0000510A 770B <1> ja short writei_1 ; 1f 25484 <1> ; bgt 1f / any bytes to output; yes, branch 25485 <1> 25486 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 25487 0000510C 83F810 <1> cmp eax, 16 ; LPR_INODE ; lpt (parallel port printer) ? 25488 0000510F 7505 <1> jne short writei_0 25489 00005111 E943010000 <1> jmp lpr_stat ; get/read line status 25490 <1> writei_0: 25491 00005116 C3 <1> retn 25492 <1> ; ; rts r0 / no, return - no writing to do 25493 <1> writei_1: ;1: 25494 <1> ; ; mov r1 ,-(sp) / save the i-node number on the stack 25495 <1> ;cmp ax, 40 25496 <1> ; ; cmp r1,$40. 25497 <1> ; ; / does the i-node number indicate a special file? 25498 <1> ;ja dskw 25499 <1> ; ; bgt dskw / no, branch to standard file output 25500 <1> 25501 <1> ; 28/11/2021 25502 00005117 F605[166D0000]FF <1> test byte [u.kcall], 0FFh 25503 0000511E 750C <1> jnz short writei_2 ; 'writei' called by 'mkdir' 25504 <1> 25505 <1> ; eax = inode number 25506 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 25507 00005120 E850FAFFFF <1> call iget 25508 <1> ;writei_2: 25509 <1> ; 28/11/2021 25510 <1> ; eax = inode number 25511 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 25512 00005125 E8E2020000 <1> call is_regular_file 25513 <1> ;jz dskw ; regular file 25514 <1> ; 25/12/2021 25515 0000512A 7505 <1> jnz short writei_5 ; device file 25516 <1> writei_2: ; 09/03/2022 25517 <1> ; regular file 25518 0000512C E968010000 <1> jmp dskw 25519 <1> writei_5: 25520 <1> ; (20/05/2015) 25521 00005131 50 <1> push eax ; because subroutines will jump to 'ret_' 25522 <1> 25523 <1> ; 28/11/2021 25524 <1> ; device file 25525 00005132 BB[4C510000] <1> mov ebx, writei_4 25526 00005137 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 25527 0000513A 720E <1> jb short writei_3 25528 0000513C 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 25529 0000513F 7709 <1> ja short writei_3 ; 11/12/2021 25530 <1> 25531 <1> ; convert v2 inode number to v1 device inode number 25532 00005141 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 25533 00005143 89C1 <1> mov ecx, eax 25534 00005145 C0E102 <1> shl cl, 2 ; * 4 25535 00005148 01CB <1> add ebx, ecx 25536 <1> writei_3: 25537 0000514A FF23 <1> jmp dword [ebx] 25538 <1> ; jmp *1f-2(r1) 25539 <1> ; / jump table and jump to the appropriate routine 25540 <1> writei_4: ;1: 25541 0000514C [7E4F0000] <1> dd null ; 28/11/2021 25542 00005150 [9C510000] <1> dd wtty ; tty, AX = 1 (runix) 25543 <1> ;wtty / tty; r1=2 25544 <1> ;wppt / ppt; r1=4 25545 00005154 [EF510000] <1> dd wmem ; mem, AX = 2 (runix) 25546 <1> ;wmem / mem; r1=6 25547 <1> ;wrf0 / rf0 25548 <1> ;wrk0 / rk0 25549 <1> ;wtap / tap0 25550 <1> ;wtap / tap1 25551 <1> ;wtap / tap2 25552 <1> ;wtap / tap3 25553 <1> ;wtap / tap4 25554 <1> ;wtap / tap5 25555 <1> ;wtap / tap6 25556 <1> ;wtap / tap7 25557 00005158 [C6580000] <1> dd wfd ; fd0, AX = 3 (runix only) 25558 0000515C [C6580000] <1> dd wfd ; fd1, AX = 4 (runix only) 25559 00005160 [C6580000] <1> dd whd ; hd0, AX = 5 (runix only) 25560 00005164 [C6580000] <1> dd whd ; hd1, AX = 6 (runix only) 25561 00005168 [C6580000] <1> dd whd ; hd2, AX = 7 (runix only) 25562 0000516C [C6580000] <1> dd whd ; hd3, AX = 8 (runix only) 25563 00005170 [1F520000] <1> dd wlpr ; lpr, AX = 9 (runix) 25564 00005174 [E9510000] <1> dd xmtt ; tty0, AX = 10 (runix) 25565 <1> ;xmtt / tty0 25566 00005178 [E9510000] <1> dd xmtt ; tty1, AX = 11 (runix) 25567 <1> ;xmtt / tty1 25568 0000517C [E9510000] <1> dd xmtt ; tty2, AX = 12 (runix) 25569 <1> ;xmtt / tty2 25570 00005180 [E9510000] <1> dd xmtt ; tty3, AX = 13 (runix) 25571 <1> ;xmtt / tty3 25572 00005184 [E9510000] <1> dd xmtt ; tty4, AX = 14 (runix) 25573 <1> ;xmtt / tty4 25574 00005188 [E9510000] <1> dd xmtt ; tty5, AX = 15 (runix) 25575 <1> ;xmtt / tty5 25576 0000518C [E9510000] <1> dd xmtt ; tty6, AX = 16 (runix) 25577 <1> ;xmtt / tty6 25578 00005190 [E9510000] <1> dd xmtt ; tty7, AX = 17 (runix) 25579 <1> ;xmtt / tty7 25580 00005194 [E9510000] <1> dd xmtt ; COM1, AX = 18 (runix only) 25581 <1> ; / wlpr / lpr 25582 00005198 [E9510000] <1> dd xmtt ; COM2, AX = 19 (runix only) 25583 <1> 25584 <1> ; ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 25585 <1> ;null: 25586 <1> ; xor eax, eax 25587 <1> ; pop eax 25588 <1> ; retn 25589 <1> 25590 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 25591 <1> wtty: ; write to console tty (write to screen) 25592 <1> ; 18/11/2015 25593 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25594 <1> ; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1) 25595 <1> ; 25596 <1> ; Console tty output is on current video page 25597 <1> ; Console tty character output procedure is changed here 25598 <1> ; acconding to IBM PC compatible ROM BIOS video (text mode) functions. 25599 <1> ; 25600 0000519C 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 25601 000051A3 8AA3[A3680000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 25602 000051A9 88E0 <1> mov al, ah ; 07/07/2014 25603 <1> wttys: 25604 <1> ; 10/10/2013 25605 000051AB 8825[D96C0000] <1> mov [u.ttyn], ah 25606 <1> ; 13/01/2014 25607 000051B1 FEC0 <1> inc al 25608 000051B3 A2[DB6C0000] <1> mov [u.ttyp+1], al ; tty number + 1 25609 <1> wtty_nc: ; 15/05/2013 25610 <1> ; AH = [u.ttyn] = tty number ; 28/07/2013 25611 000051B8 E870010000 <1> call cpass 25612 <1> ; jsr r0,cpass / get next character from user buffer area; if 25613 <1> ; / none go to return address in syswrite 25614 <1> ; tst r1 / is character = null 25615 <1> ; beq wtty / yes, get next character 25616 <1> ; 10/10/2013 25617 000051BD 7428 <1> jz short wret 25618 <1> ;1 : 25619 <1> ;mov $240,*$ps / no, set processor priority to five 25620 <1> ;cmpb cc+1,$20. / is character count for console tty greater 25621 <1> ; / than 20 25622 <1> ;bhis 2f / yes; branch to put process to sleep 25623 <1> ; 27/06/2014 25624 <1> wtty_1: 25625 <1> ; AH = tty number 25626 <1> ; AL = ASCII code of the character 25627 <1> ; 15/04/2014 25628 <1> ;push ax 25629 <1> ; 11/12/2021 25630 000051BF 50 <1> push eax 25631 000051C0 E8120A0000 <1> call putc ; 14/05/2013 25632 000051C5 731D <1> jnc short wtty_2 25633 <1> ; 18/11/2015 25634 000051C7 E827F5FFFF <1> call idle 25635 <1> ;mov ax, [esp] 25636 <1> ; 11/12/2021 25637 000051CC 8B0424 <1> mov eax, [esp] 25638 000051CF E8030A0000 <1> call putc 25639 000051D4 730E <1> jnc short wtty_2 25640 <1> ; 02/06/2014 25641 000051D6 8A25[D96C0000] <1> mov ah, [u.ttyn] 25642 000051DC E89FF5FFFF <1> call sleep 25643 <1> ;pop ax 25644 <1> ; 11/12/2021 25645 000051E1 58 <1> pop eax 25646 000051E2 EBDB <1> jmp short wtty_1 25647 <1> ; jc error ; 15/05/2013 (COM1 or COM2 serial port error) 25648 <1> ; jsr r0,putc; 1 / find place in freelist to assign to 25649 <1> ; / console tty and 25650 <1> ; br 2f / place character in list; if none available 25651 <1> ; / branch to put process to sleep 25652 <1> ; jsr r0,startty / attempt to output character on tty 25653 <1> wtty_2: 25654 <1> ; 15/04/2014 25655 <1> ;pop ax 25656 <1> ; 11/12/2021 25657 000051E4 58 <1> pop eax 25658 000051E5 EBD1 <1> jmp short wtty_nc 25659 <1> ; br wtty 25660 <1> wret: ; 10/10/2013 (20/05/2015) 25661 000051E7 58 <1> pop eax 25662 000051E8 C3 <1> retn 25663 <1> ;2: 25664 <1> ;mov r1,-(sp) / place character on stack 25665 <1> ;jsr r0,sleep; 1 / put process to sleep 25666 <1> ;mov (sp)+,r1 / remove character from stack 25667 <1> ;br 1b / try again to place character in clist and output 25668 <1> 25669 <1> xmtt: ; < send/write character to tty > 25670 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25671 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 25672 <1> ; 25673 <1> ; Retro UNIX 8086 v1 modification ! 25674 <1> ; 25675 <1> ; In original UNIX v1, 'xmtt' routine 25676 <1> ; (exactly different than this one) 25677 <1> ; was in 'u9.s' file. 25678 <1> ; 25679 000051E9 2C0A <1> sub al, 10 25680 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 25681 <1> ; 10/10/2013 25682 000051EB 88C4 <1> mov ah, al 25683 <1> ; 28/07/2013 25684 000051ED EBBC <1> jmp short wttys 25685 <1> 25686 <1> ;wppt: 25687 <1> ; jsr r0,cpass / get next character from user buffer area, 25688 <1> ; / if none return to writei's calling routine 25689 <1> ; jsr r0,pptoc / output character on ppt 25690 <1> ; br wppt 25691 <1> 25692 <1> wmem: ; / transfer characters from a user area of core to memory file 25693 <1> ; 17/10/2015 25694 <1> ; 11/06/2015 25695 <1> ; 24/05/2015 25696 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 25697 <1> ; 25698 000051EF 813D[09070000]- <1> cmp dword [x_timer], clock ; multi tasking clock/timer 25699 000051F5 [16470000] <1> 25700 000051F9 7415 <1> je short wmem_acc_err 25701 <1> ; 25702 000051FB 8B35[B86C0000] <1> mov esi, [u.fofp] 25703 <1> wmem_1: 25704 00005201 E827010000 <1> call cpass 25705 <1> ; jsr r0,cpass / get next character from users area of 25706 <1> ; / core and put it in r1 25707 <1> ; mov r1,-(sp) / put character on the stack 25708 <1> ; 20/09/2013 25709 00005206 74DF <1> jz short wret ; wmem_2 25710 00005208 8B1E <1> mov ebx, [esi] 25711 <1> ; mov *u.fofp,r1 / save file offset in r1 25712 0000520A FF06 <1> inc dword [esi] ; 17/10/2015 25713 <1> ; inc *u.fofp / increment file offset to point to next 25714 <1> ; / available location in file 25715 0000520C 8803 <1> mov [ebx], al 25716 <1> ; movb (sp)+,(r1) / pop char off stack, put in memory loc 25717 <1> ; / assigned to it 25718 0000520E EBF1 <1> jmp short wmem_1 25719 <1> ; br wmem / continue 25720 <1> ;1: 25721 <1> ;jmp error / ? 25722 <1> ;wmem_2: 25723 <1> ; ; 20/09/2013 25724 <1> ; pop ax 25725 <1> ; retn 25726 <1> 25727 <1> wmem_acc_err: 25728 00005210 C705[186D0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 25729 00005218 0000 <1> 25730 0000521A E946DFFFFF <1> jmp error 25731 <1> 25732 <1> ;wlpr: 25733 <1> ; 12/06/2022 25734 <1> ;mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 25735 <1> ;jmp error ; ... Printing procedure will be located here ... 25736 <1> ;/ jsr r0,cpass 25737 <1> ;/ cmp r0,$'a 25738 <1> ;/ blo 1f 25739 <1> ;/ cmp r1,$'z 25740 <1> ;/ bhi 1f 25741 <1> ;/ sub $40,r1 25742 <1> ;/1: 25743 <1> ;/ jsr r0,lptoc 25744 <1> ;/ br wlpr 25745 <1> ; br rmem / continue 25746 <1> 25747 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 - PRINTER BIOS (Functions) 25748 <1> 25749 <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM) 25750 <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987 25751 <1> ;; 23/03/2018 - Retro DOS v2.0 25752 <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2) 25753 <1> 25754 <1> ; IBM ROMBIOS (INT 17h) STATUS BITS 25755 <1> 25756 <1> NOTBUSYSTATUS equ 10000000b ; NOT BUSY 25757 <1> ACKSTATUS equ 01000000b ; ACKNOWLEDGE (FOR WHAT?) 25758 <1> NOPAPERSTATUS equ 00100000b ; NO MORE PAPER 25759 <1> SELECTEDSTATUS equ 00010000b ; THE PRINTER SAID IT WAS SELECTED 25760 <1> IOERRSTATUS equ 00001000b ; SOME KIND ERROR 25761 <1> RESERVED equ 00000110b ; NOPS 25762 <1> TIMEOUTSTATUS equ 00000001b ; TIME OUT. 25763 <1> 25764 <1> ;---------------------------------------------------------------- 25765 <1> ; : 25766 <1> ; WRITE TO PRINTER DEVICE : 25767 <1> ; : 25768 <1> ; CX has count of bytes to be printed : 25769 <1> ; ES:DI point to source buffer contains characters : 25770 <1> ; AuxNum (in msbio.asm) has printer number : 25771 <1> ; : 25772 <1> ;---------------------------------------------------------------- 25773 <1> 25774 <1> wlpr: 25775 <1> ; 15/07/2022 25776 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 25777 <1> PRN$WRIT: 25778 <1> ; INPUT: 25779 <1> ; [u.count] = count of characters to be printed 25780 <1> ; [u.base] = buffer address in user's memory space 25781 <1> ; 25782 <1> ; (if ECX = 0, printer status will be returned) 25783 <1> 25784 <1> ;xor ebx, ebx 25785 <1> PRN$LOOP: 25786 0000521F E809010000 <1> call cpass ; Get a character into AL 25787 00005224 7431 <1> jz short pr_exit 25788 <1> ; 25789 00005226 B302 <1> mov bl, 2 ; retry count 25790 <1> PRN$OUT: 25791 <1> ; al = character which will be printed 25792 00005228 30E4 <1> xor ah, ah ; 0 ; PRINT THE CHARACTER IN (AL) 25793 0000522A E850000000 <1> call PRNOP 25794 0000522F 74EE <1> jz short PRN$LOOP ; if error, try to print again 25795 <1> PrRetry: 25796 <1> ; al = character 25797 00005231 FECB <1> dec bl 25798 00005233 75F3 <1> jnz short PRN$OUT 25799 <1> pr_err_exit: 25800 00005235 0FB6C0 <1> movzx eax, al 25801 00005238 A3[186D0000] <1> mov [u.error], eax 25802 0000523D A3[A46C0000] <1> mov [u.r0], eax ; error code in AL 25803 <1> ;mov ebp, [u.sp] 25804 00005242 8B1D[9C6C0000] <1> mov ebx, [u.sp] ; 15/07/2022 25805 <1> ; Kernel stack at the beginning of sys call 25806 00005248 8B15[D06C0000] <1> mov edx, [u.nread] 25807 0000524E 4A <1> dec edx ; last char failed 25808 <1> ;mov [ebp+20], edx ; count of printed characters in edx 25809 0000524F 895314 <1> mov [ebx+20], edx ; 15/07/2022 25810 00005252 E90EDFFFFF <1> jmp error 25811 <1> pr_exit: 25812 00005257 58 <1> pop eax ; inode number 25813 <1> 25814 <1> ;mov eax, [u.nread] 25815 <1> ;mov [u.r0], eax ; count of printed chacters 25816 <1> ;jmp sysret 25817 00005258 C3 <1> retn ; return from writei to syswrite (rw0) 25818 <1> 25819 <1> ; 12/06/2022 25820 <1> 25821 <1> ;---------------------------------------------------------------- 25822 <1> ; : 25823 <1> ; PRINTER STATUS ROUTINE : 25824 <1> ; : 25825 <1> ;---------------------------------------------------------------- 25826 <1> ; 25827 <1> 25828 <1> lpr_stat: 25829 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 25830 <1> PRN$STAT: 25831 00005259 E81F000000 <1> call PRNSTAT ; get the status 25832 0000525E 750E <1> jnz short prn_stat_retn 25833 <1> ; if error jump to error routine 25834 <1> ;mov al, 9 ; AGAIN, ASSUME OUT OF PAPER... 25835 00005260 B01F <1> mov al, ERR_PRN_PAPER 25836 00005262 F6C420 <1> test ah, NOPAPERSTATUS 25837 00005265 7507 <1> jnz short prn_stat_retn 25838 00005267 F6C480 <1> test ah, NOTBUSYSTATUS 25839 0000526A 750D <1> jnz short prn_stat_ok ; if not busy return (with cf=0) 25840 0000526C B022 <1> mov al, ERR_PRN_BUSY ; else busy, return to busy exit 25841 <1> prn_stat_retn: 25842 <1> ; al = error code 25843 <1> ; ah = status flags 25844 0000526E A3[A46C0000] <1> mov [u.r0], eax 25845 <1> ;movzx eax, al 25846 <1> ;mov [u.error], eax 25847 00005273 58 <1> pop eax ; discard return address to syswrite 25848 00005274 E90CDFFFFF <1> jmp sysret 25849 <1> prn_stat_ok: 25850 00005279 30C0 <1> xor al, al ; 0 25851 0000527B EBF1 <1> jmp short prn_stat_retn 25852 <1> 25853 <1> ; 25854 <1> ; PRNSTAT get printer status 25855 <1> ; PRNOP print a character 25856 <1> ; 25857 <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS 25858 <1> ; printer routines. The routines share code which calls on the bios and 25859 <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ 25860 <1> ; only by the value put into AH before the ROM-BIOS call. 25861 <1> ; 25862 <1> ; INPUT if PRNOP then character in AL 25863 <1> ; 25864 <1> ; OUTPUT - AL holds error code 25865 <1> ; - AH status byte from printer 25866 <1> ; - flag NZ if error 25867 <1> 25868 <1> PRNSTAT: 25869 0000527D B402 <1> mov ah, 2 ; set command for get status 25870 <1> 25871 <1> PRNOP: 25872 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 25873 <1> ; 25874 <1> ; Print character (on paper) 25875 <1> 25876 <1> ; INPUT: 25877 <1> ; al = character to be printed 25878 <1> ; OUTPUT: 25879 <1> ; zf = 1 -> ok 25880 <1> ; zf = 0 -> error code in AL 25881 <1> 25882 0000527F E8DC0B0000 <1> call int17h ; call lpt bios 25883 <1> 25884 00005284 F6C408 <1> test ah, IOERRSTATUS ; I/O ERROR? 25885 00005287 740A <1> jz short short prnop_chk_nrdy ; NO, TRY NOT READY 25886 <1> 25887 <1> ; AT THIS POINT, WE KNOW WE HAVE AN ERROR. 25888 <1> ; THE CONVERSE IS NOT TRUE. 25889 <1> 25890 <1> ;mov al, 9 ; FIRST, ASSUME OUT OF PAPER 25891 00005289 B01F <1> mov al, ERR_PRN_PAPER 25892 0000528B F6C420 <1> test ah, NOPAPERSTATUS ; OUT OF PAPER SET? 25893 0000528E 7502 <1> jnz short PRNOP1 ; YES, ERROR IS SET 25894 <1> ;mov al, ERR_PRN_IO 25895 00005290 FEC0 <1> inc al ; INDICATE I/O ERROR 25896 <1> PRNOP1: 25897 <1> 25898 <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT) 25899 <1> 25900 00005292 C3 <1> retn ; RETURN WITH ERROR 25901 <1> 25902 <1> ; THE BITS SAID NO ERROR. 25903 <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE. 25904 <1> 25905 <1> prnop_chk_nrdy: 25906 <1> ;mov al, 2 ; ASSUME NOT-READY 25907 00005293 B019 <1> mov al, ERR_PRN_TIMEOUT ; ''time out !' error 25908 <1> 25909 00005295 F6C401 <1> test ah, TIMEOUTSTATUS ; IS TIME-OUT SET? 25910 <1> ; IF NZ THEN ERROR, ELSE OK??? 25911 <1> PRNOP2: 25912 00005298 C3 <1> retn 25913 <1> 25914 <1> 25915 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 25916 <1> 25917 <1> dskw: ; / write routine for non-special files 25918 <1> ; 25919 <1> ; 19/07/2022 25920 <1> ; (file offset bugfix for 'dskwr' error return situation) 25921 <1> ; 28/11/2021 25922 <1> ; 25/07/2015 25923 <1> ; 16/06/2015 25924 <1> ; 09/06/2015 25925 <1> ; 31/05/2015 (Retro UNIX 386 v1 - Beginning) 25926 <1> ; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1) 25927 <1> 25928 <1> ; 01/08/2013 (mkdir_w check) 25929 <1> ;push ax ; 26/04/2013 25930 <1> ; ; mov (sp),r1 / get an i-node number from the stack into r1 25931 <1> ; 28/11/2021 25932 00005299 50 <1> push eax 25933 <1> ; AX = inode number 25934 0000529A E8D6F8FFFF <1> call iget 25935 <1> ; jsr r0,iget / write i-node out (if modified), 25936 <1> ; / read i-node 'r1' into i-node area of core 25937 0000529F 8B1D[B86C0000] <1> mov ebx, [u.fofp] 25938 000052A5 8B13 <1> mov edx, [ebx] 25939 <1> ; mov *u.fofp,r2 / put the file offset [(u.off) or the offset 25940 <1> ; / in the fsp entry for this file] in r2 25941 000052A7 0315[CC6C0000] <1> add edx, [u.count] 25942 <1> ; add u.count,r2 / no. of bytes to be written 25943 <1> ; / + file offset is put in r2 25944 <1> ;; 16/06/2015 25945 <1> ;cmp edx, 65535 ; file size limit (for UNIX v1 file system) 25946 <1> ;jna short dskw_0 25947 <1> ;mov dword [u.error], ERR_FILE_SIZE ; 'file size error !' 25948 <1> ;jmp error 25949 <1> dskw_0: 25950 <1> ; 28/11/2021 25951 000052AD 3B15[2C680000] <1> cmp edx, [i.size] ; 32 bit file size (runix v2 inode) 25952 <1> ;cmp dx, [i.size] 25953 <1> ; ; cmp r2,i.size / is this greater than the present size of 25954 <1> ; / the file? 25955 000052B3 760B <1> jna short dskw_1 25956 <1> ; blos 1f / no, branch 25957 000052B5 8915[2C680000] <1> mov [i.size], edx ; 32 bit file size (runix v2 inode) 25958 <1> ;mov [i.size], dx 25959 <1> ; mov r2,i.size / yes, increase the file size to 25960 <1> ; / file offset + no. of data bytes 25961 000052BB E846FAFFFF <1> call setimod 25962 <1> ; jsr r0,setimod / set imod=1 (i.e., core inode has been 25963 <1> ; / modified), stuff time of modification into 25964 <1> ; / core image of i-node 25965 <1> dskw_1: ; 1: 25966 <1> ; 28/11/2021 25967 <1> ;call mget 25968 000052C0 E833F5FFFF <1> call mget_w 25969 <1> ; jsr r0,mget / get the block no. in which to write 25970 <1> ; / the next data byte 25971 <1> ; eax = physical block/sector number 25972 000052C5 8B1D[B86C0000] <1> mov ebx, [u.fofp] 25973 000052CB 8B13 <1> mov edx, [ebx] 25974 000052CD 81E2FF010000 <1> and edx, 1FFh 25975 <1> ; bit *u.fofp,$777 / test the lower 9 bits of the file offset 25976 000052D3 750C <1> jnz short dskw_2 25977 <1> ; bne 2f / if its non-zero, branch; if zero, file offset = 0, 25978 <1> ; / 512, 1024,...(i.e., start of new block) 25979 000052D5 813D[CC6C0000]0002- <1> cmp dword [u.count], 512 25980 000052DD 0000 <1> 25981 <1> ; cmp u.count,$512. / if zero, is there enough data to fill 25982 <1> ; / an entire block? (i.e., no. of 25983 000052DF 7305 <1> jnb short dskw_3 25984 <1> ; bhis 3f / bytes to be written greater than 512.? 25985 <1> ; / Yes, branch. Don't have to read block 25986 <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be 25987 <1> ; / overwritten). 25988 000052E1 E8AA060000 <1> call dskrd 25989 <1> ; jsr r0,dskrd / no, must retain old info.. 25990 <1> ; / Hence, read block 'r1' into an I/O buffer 25991 <1> dskw_3: ; 3: 25992 <1> ; EAX (r1) = block/sector number 25993 000052E6 E809070000 <1> call wslot 25994 <1> ; jsr r0,wslot / set write and inhibit bits in I/O queue, 25995 <1> ; / proc. status=0, r5 points to 1st word of data 25996 000052EB 803D[166D0000]00 <1> cmp byte [u.kcall], 0 25997 000052F2 770F <1> ja short dskw_5 ; zf=0 -> the caller is 'mkdir' 25998 <1> ; 25999 000052F4 66833D[106D0000]00 <1> cmp word [u.pcount], 0 26000 000052FC 7705 <1> ja short dskw_5 26001 <1> dskw_4: 26002 <1> ; [u.base] = virtual address to transfer (as source address) 26003 000052FE E895FDFFFF <1> call trans_addr_r ; translate virtual address to physical (r) 26004 <1> dskw_5: 26005 <1> ; eBX (r5) = system (I/O) buffer address 26006 00005303 E885000000 <1> call sioreg 26007 <1> ; jsr r0,sioreg / r3 = no. of bytes of data, 26008 <1> ; / r1 = address of data, r2 points to location 26009 <1> ; / in buffer in which to start writing data 26010 <1> ; 19/07/2022 26011 <1> ; EDX = user data offset (previous value of [u.pbase]) 26012 <1> ; ESI = pointer to file offset 26013 <1> ; EDI = system (I/O) buffer offset 26014 <1> ; ECX = byte count 26015 <1> ; EBX = system buffer (data) address 26016 <1> ; EAX = remain bytes after byte count within page frame 26017 <1> 26018 <1> ; 19/07/2022 - Erdogan Tan 26019 <1> ; BugFix (Also original unix v1 kernel code has this bug!) 26020 <1> ; ((Against a possible disk write failure/error, 26021 <1> ; file offset must not be updated/increased before 'dskwr' 26022 <1> ; but it was updated in 'sioreg'. I have modified 'sioreg' 26023 <1> ; and 'dskw' procedures for that.)) 26024 <1> 26025 <1> ; 19/07/2022 26026 00005308 56 <1> push esi ; * ; save file offset (pointer) 26027 00005309 51 <1> push ecx ; ** ; save byte count 26028 0000530A 89D6 <1> mov esi, edx 26029 <1> 26030 <1> ; ESI = file (user data) offset 26031 <1> ; EDI = sector (I/O) buffer offset 26032 <1> ; ECX = byte count 26033 <1> ; 26034 0000530C F3A4 <1> rep movsb 26035 <1> ; movb (r1 )+,(r2)+ 26036 <1> ; / transfer a byte of data to the I/O buffer 26037 <1> ; dec r3 / decrement no. of bytes to be written 26038 <1> ; bne 2b / have all bytes been transferred? No, branch 26039 <1> ; 25/07/2015 26040 <1> ; eax = remain bytes in buffer 26041 <1> ; (check if remain bytes in the buffer > [u.pcount]) 26042 0000530E 09C0 <1> or eax, eax 26043 00005310 75EC <1> jnz short dskw_4 ; (page end before system buffer end!) 26044 <1> dskw_6: 26045 00005312 E8EA060000 <1> call dskwr 26046 <1> ; jsr r0,dskwr / yes, write the block and the i-node 26047 <1> 26048 <1> ; 19/07/2022 26049 <1> ; (there is not a disk write error, we can increase file offset) 26050 00005317 58 <1> pop eax ; ** ; byte count 26051 00005318 5F <1> pop edi ; * ; file offset (pointer) 26052 <1> ; 26053 00005319 0107 <1> add [edi], eax 26054 <1> ; new file offset (old offset + byte count) 26055 <1> 26056 0000531B 833D[CC6C0000]00 <1> cmp dword [u.count], 0 26057 <1> ; tst u.count / any more data to write? 26058 00005322 779C <1> ja short dskw_1 26059 <1> ; bne 1b / yes, branch 26060 <1> ; 03/08/2013 26061 00005324 C605[166D0000]00 <1> mov byte [u.kcall], 0 26062 <1> ; 20/09/2013 (;;) 26063 <1> ;pop ax 26064 <1> ; 28/11/2021 26065 0000532B 58 <1> pop eax 26066 0000532C C3 <1> retn 26067 <1> ;;jmp short dskw_ret 26068 <1> ; jmp ret / no, return to the caller via 'ret' 26069 <1> 26070 <1> ; 24/12/2021 26071 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 26072 <1> cpass: ; / get next character from user area of core and put it in r1 26073 <1> ; 18/10/2015 26074 <1> ; 10/10/2015 26075 <1> ; 10/07/2015 26076 <1> ; 02/07/2015 26077 <1> ; 01/07/2015 26078 <1> ; 24/06/2015 26079 <1> ; 08/06/2015 26080 <1> ; 04/06/2015 26081 <1> ; 20/05/2015 26082 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 26083 <1> ; 26084 <1> ; INPUTS -> 26085 <1> ; [u.base] = virtual address in user area 26086 <1> ; [u.count] = byte count (max.) 26087 <1> ; [u.pcount] = byte count in page (0 = reset) 26088 <1> ; OUTPUTS -> 26089 <1> ; AL = the character which is pointed by [u.base] 26090 <1> ; zf = 1 -> transfer count has been completed 26091 <1> ; 26092 <1> ; ((Modified registers: EAX, EDX, ECX)) 26093 <1> ; 26094 <1> ; 26095 0000532D 833D[CC6C0000]00 <1> cmp dword [u.count], 0 ; 14/08/2013 26096 <1> ; tst u.count / have all the characters been transferred 26097 <1> ; / (i.e., u.count, # of chars. left 26098 00005334 763F <1> jna short cpass_3 26099 <1> ; beq 1f / to be transferred = 0?) yes, branch 26100 00005336 FF0D[CC6C0000] <1> dec dword [u.count] 26101 <1> ; dec u.count / no, decrement u.count 26102 <1> ; 19/05/2015 26103 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 26104 <1> ; to physical address 26105 0000533C 66833D[106D0000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 26106 <1> ; 1-4095 --> use previous physical base address 26107 <1> ; in [u.pbase] 26108 00005344 770E <1> ja short cpass_1 26109 <1> ; 02/07/2015 26110 00005346 833D[086D0000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller os kernel 26111 0000534D 7427 <1> je short cpass_k ; (sysexec, '/etc/init') ? 26112 <1> ; 08/06/2015 - 10/07/2015 26113 0000534F E844FDFFFF <1> call trans_addr_r 26114 <1> cpass_1: 26115 <1> ; 02/07/2015 26116 <1> ; 24/06/2015 26117 00005354 66FF0D[106D0000] <1> dec word [u.pcount] 26118 <1> cpass_2: 26119 <1> ; 10/10/2015 26120 <1> ; 02/07/2015 26121 0000535B 8B15[0C6D0000] <1> mov edx, [u.pbase] 26122 00005361 8A02 <1> mov al, [edx] ; 10/10/2015 26123 <1> ; movb *u.base,r1 / take the character pointed to 26124 <1> ; / by u.base and put it in r1 26125 00005363 FF05[D06C0000] <1> inc dword [u.nread] 26126 <1> ; inc u.nread / increment no. of bytes transferred 26127 00005369 FF05[C86C0000] <1> inc dword [u.base] 26128 <1> ; inc u.base / increment the buffer address to point to the 26129 <1> ; / next byte 26130 0000536F FF05[0C6D0000] <1> inc dword [u.pbase] ; 04/06/2015 26131 <1> cpass_3: 26132 00005375 C3 <1> retn 26133 <1> ; rts r0 / next byte 26134 <1> ; 1: 26135 <1> ; mov (sp)+,r0 26136 <1> ; / put return address of calling routine into r0 26137 <1> ; mov (sp)+,r1 / i-number in r1 26138 <1> ; rts r0 / non-local return 26139 <1> cpass_k: 26140 <1> ; 02/07/2015 26141 <1> ; The caller is os kernel 26142 <1> ; (get sysexec arguments from kernel's memory space) 26143 <1> ; 26144 00005376 8B1D[C86C0000] <1> mov ebx, [u.base] 26145 0000537C 66C705[106D0000]00- <1> mov word [u.pcount], PAGE_SIZE ; 4096 26146 00005384 10 <1> 26147 00005385 891D[0C6D0000] <1> mov [u.pbase], ebx 26148 0000538B EBCE <1> jmp short cpass_2 26149 <1> 26150 <1> sioreg: 26151 <1> ; 19/07/2022 26152 <1> ; (file offset bugfix for 'dskwr' error return situation) 26153 <1> ; 25/07/2015 26154 <1> ; 18/07/2015 26155 <1> ; 02/07/2015 26156 <1> ; 17/06/2015 26157 <1> ; 09/06/2015 26158 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 26159 <1> ; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1) 26160 <1> ; 26161 <1> ; INPUTS -> 26162 <1> ; EBX = system buffer (data) address (r5) 26163 <1> ; [u.fofp] = pointer to file offset pointer 26164 <1> ; [u.base] = virtual address of the user buffer 26165 <1> ; [u.pbase] = physical address of the user buffer 26166 <1> ; [u.count] = byte count 26167 <1> ; [u.pcount] = byte count within page frame 26168 <1> ; OUTPUTS -> 26169 <1> ; ESI = user data offset (r1) 26170 <1> ; EDI = system (I/O) buffer offset (r2) 26171 <1> ; ECX = byte count (r3) 26172 <1> ; EAX = remain bytes after byte count within page frame 26173 <1> ; (If EAX > 0, transfer will continue from the next page) 26174 <1> ; 26175 <1> ; ((Modified registers: EDX)) 26176 <1> 26177 <1> ; 19/07/2022 26178 <1> ; OUTPUTS -> 26179 <1> ; EDX = user data offset (previous value of [u.pbase]) 26180 <1> ; ESI = pointer to file offset 26181 <1> ; EDI = system (I/O) buffer offset 26182 <1> ; ECX = byte count 26183 <1> ; EBX = system buffer (data) address 26184 <1> ; EAX = remain bytes after byte count within page frame 26185 <1> 26186 0000538D 8B35[B86C0000] <1> mov esi, [u.fofp] 26187 00005393 8B3E <1> mov edi, [esi] 26188 <1> ; mov *u.fofp,r2 / file offset (in bytes) is moved to r2 26189 00005395 89F9 <1> mov ecx, edi 26190 <1> ; mov r2,r3 / and also to r3 26191 00005397 81C900FEFFFF <1> or ecx, 0FFFFFE00h 26192 <1> ; bis $177000,r3 / set bits 9,...,15 of file offset in r3 26193 0000539D 81E7FF010000 <1> and edi, 1FFh 26194 <1> ; bic $!777,r2 / calculate file offset mod 512. 26195 000053A3 01DF <1> add edi, ebx ; EBX = system buffer (data) address 26196 <1> ; add r5,r2 / r2 now points to 1st byte in system buffer 26197 <1> ; / where data is to be placed 26198 <1> ; mov u.base,r1 / address of data is in r1 26199 000053A5 F7D9 <1> neg ecx 26200 <1> ; neg r3 / 512 - file offset (mod512.) in r3 26201 <1> ; / (i.e., the no. of free bytes in the file block) 26202 000053A7 3B0D[CC6C0000] <1> cmp ecx, [u.count] 26203 <1> ; cmp r3,u.count / compare this with the no. of data bytes 26204 <1> ; / to be written to the file 26205 000053AD 7606 <1> jna short sioreg_0 26206 <1> ; blos 2f / if less than branch. Use the no. of free bytes 26207 <1> ; / in the file block as the number to be written 26208 000053AF 8B0D[CC6C0000] <1> mov ecx, [u.count] 26209 <1> ; mov u.count,r3 / if greater than, use the no. of data 26210 <1> ; / bytes as the number to be written 26211 <1> sioreg_0: 26212 <1> ; 17/06/2015 26213 000053B5 803D[166D0000]00 <1> cmp byte [u.kcall], 0 26214 000053BC 7613 <1> jna short sioreg_1 26215 <1> ; 25/07/2015 26216 <1> ; the caller is 'mkdir' or 'namei' 26217 000053BE A1[C86C0000] <1> mov eax, [u.base] ; 25/07/2015 26218 000053C3 A3[0C6D0000] <1> mov [u.pbase], eax ; physical address = virtual address 26219 000053C8 66890D[106D0000] <1> mov word [u.pcount], cx ; remain bytes in buffer (1 sector) 26220 000053CF EB0B <1> jmp short sioreg_2 26221 <1> sioreg_1: 26222 <1> ; 25/07/2015 26223 <1> ; 18/07/2015 26224 <1> ; 09/06/2015 26225 000053D1 0FB715[106D0000] <1> movzx edx, word [u.pcount] 26226 <1> ; ecx and [u.pcount] are always > 0, here 26227 000053D8 39D1 <1> cmp ecx, edx 26228 000053DA 7728 <1> ja short sioreg_4 ; transfer count > [u.pcount] 26229 <1> sioreg_2: ; 2: 26230 000053DC 31C0 <1> xor eax, eax ; 25/07/2015 26231 <1> sioreg_3: 26232 000053DE 010D[D06C0000] <1> add [u.nread], ecx 26233 <1> ; add r3,u.nread / r3 + number of bytes xmitted 26234 <1> ; / during write is put into u.nread 26235 000053E4 290D[CC6C0000] <1> sub [u.count], ecx 26236 <1> ; sub r3,u.count / u.count = no. of bytes that still 26237 <1> ; / must be written or read 26238 000053EA 010D[C86C0000] <1> add [u.base], ecx 26239 <1> ; add r3,u.base / u.base points to the 1st of the remaining 26240 <1> ; / data bytes 26241 <1> ; 19/07/2022 26242 <1> ;add [esi], ecx 26243 <1> ; ; add r3,*u.fofp / new file offset = number of bytes done 26244 <1> ; / + old file offset 26245 <1> ; 25/07/2015 26246 <1> ;mov esi, [u.pbase] 26247 <1> ; 19/07/2022 26248 000053F0 8B15[0C6D0000] <1> mov edx, [u.pbase] 26249 <1> 26250 000053F6 66290D[106D0000] <1> sub [u.pcount], cx 26251 000053FD 010D[0C6D0000] <1> add [u.pbase], ecx 26252 00005403 C3 <1> retn 26253 <1> ; rts r0 26254 <1> ; transfer count > [u.pcount] 26255 <1> sioreg_4: 26256 <1> ; 25/07/2015 26257 <1> ; transfer count > [u.pcount] 26258 <1> ; (ecx > edx) 26259 00005404 89C8 <1> mov eax, ecx 26260 00005406 29D0 <1> sub eax, edx ; remain bytes for 1 sector (block) transfer 26261 00005408 89D1 <1> mov ecx, edx ; current transfer count = [u.pcount] 26262 0000540A EBD2 <1> jmp short sioreg_3 26263 <1> 26264 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 26265 <1> is_regular_file: 26266 <1> ; check if it is a regular file or device file inode 26267 <1> ; 26268 <1> ; INPUT: 26269 <1> ; current inode 26270 <1> ; OUTPUT: 26271 <1> ; cf = 0 and zf = 1 -> regular file 26272 <1> ; cf = 0 and zf = 0 -> device file 26273 <1> ; cf = 1 -> invalid file (jump to 'error') 26274 <1> ; 26275 <1> ; Modified registers: ecx (cl) 26276 <1> 26277 <1> ; 28/11/2021 26278 0000540C 8A0D[25680000] <1> mov cl, [i.flgs+1] 26279 00005412 F6C180 <1> test cl, 80h ; regular file ? 26280 00005415 7514 <1> jnz short isregf_1 ; yes 26281 00005417 80E120 <1> and cl, 20h ; device file ? 26282 0000541A 7511 <1> jnz short isregf_2 ; yes 26283 <1> 26284 <1> ; 28/11/2021 26285 <1> ; invalid inode/file type ! 26286 0000541C C705[186D0000]FF00- <1> mov dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file 26287 00005424 0000 <1> 26288 <1> ;stc 26289 <1> ;retn 26290 00005426 E93ADDFFFF <1> jmp error 26291 <1> isregf_1: 26292 0000542B 30C9 <1> xor cl, cl ; cl = 0 26293 <1> ; zf = 1 26294 <1> ;retn 26295 <1> isregf_2: 26296 <1> ; zf = 0 26297 <1> ; cl = 20h 26298 0000542D C3 <1> retn 26299 %include 'u7.s' ; 18/04/2015 26300 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 26301 <1> ; (re-write kernel for test by using previous version without a major defect) 26302 <1> ; **************************************************************************** 26303 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - SYS7.INC 26304 <1> ; Last Modification: 12/06/2022 26305 <1> ; ---------------------------------------------------------------------------- 26306 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 26307 <1> ; (v0.1 - Beginning: 11/07/2012) 26308 <1> ; 26309 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 26310 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 26311 <1> ; 26312 <1> ; 26313 <1> ; 26314 <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s 26315 <1> ; 26316 <1> ; **************************************************************************** 26317 <1> 26318 <1> sysmount: ; / mount file system; args special; name 26319 <1> ; 15/05/2022 26320 <1> ; 09/05/2022 26321 <1> ; (Retro UNIX 386 v1.2, Kernel v0.2.2.1) 26322 <1> ; 08/02/2022 26323 <1> ; 07/02/2022 26324 <1> ; 11/01/2022 (Retro UNIX 386 v1.2) 26325 <1> ; 14/11/2015 26326 <1> ; 24/10/2015 26327 <1> ; 13/10/2015 26328 <1> ; 10/07/2015 26329 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 26330 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 26331 <1> ; 26332 <1> ; 'sysmount' anounces to the system that a removable 26333 <1> ; file system has been mounted on a special file. 26334 <1> ; The device number of the special file is obtained via 26335 <1> ; a call to 'getspl'. It is put in the I/O queue entry for 26336 <1> ; dismountable file system (sb1) and the I/O queue entry is 26337 <1> ; set up to read (bit 10 is set). 'ppoke' is then called to 26338 <1> ; to read file system into core, i.e. the first block on the 26339 <1> ; mountable file system is read in. This block is super block 26340 <1> ; for the file system. This call is super user restricted. 26341 <1> ; 26342 <1> ; Calling sequence: 26343 <1> ; sysmount; special; name 26344 <1> ; Arguments: 26345 <1> ; special - pointer to name of special file (device) 26346 <1> ; name - pointer to name of the root directory of the 26347 <1> ; newly mounted file system. 'name' should 26348 <1> ; always be a directory. 26349 <1> ; Inputs: - 26350 <1> ; Outputs: - 26351 <1> ; ............................................................... 26352 <1> ; 26353 <1> ; Retro UNIX 8086 v1 modification: 26354 <1> ; 'sysmount' system call has two arguments; so, 26355 <1> ; * 1st argument, special is pointed to by BX register 26356 <1> ; * 2nd argument, name is in CX register 26357 <1> ; 26358 <1> ; NOTE: Device numbers, names and related procedures are 26359 <1> ; already modified for IBM PC compatibility and 26360 <1> ; Retro UNIX 8086 v1 device configuration. 26361 <1> 26362 <1> ;call arg2 26363 <1> ; jsr r0,arg2 / get arguments special and name 26364 0000542E 891D[C06C0000] <1> mov [u.namep], ebx 26365 <1> ; 07/02/2022 26366 <1> ;push ecx ; directory name 26367 <1> ;cmp dword [mnti], 0 ; 11/01/2022 (32 bit inode number) 26368 00005434 66833D[8A6C0000]00 <1> cmp word [mnti], 0 26369 <1> ; tst mnti / is the i-number of the cross device file 26370 <1> ; / zero? 26371 <1> ;;ja error 26372 <1> ; bne errora / no, error 26373 <1> ;ja sysmnt_err0 26374 <1> ; 11/01/2022 26375 0000543C 7605 <1> jna short sysmnt_0 ; 12/01/2022 26376 <1> sysmnt_0_err: 26377 0000543E E993010000 <1> jmp sysmnt_err0 26378 <1> sysmnt_0: 26379 <1> ; 07/02/2022 26380 00005443 51 <1> push ecx ; directory name 26381 00005444 E875010000 <1> call getspl 26382 <1> ; jsr r0,getspl / get special files device number in r1 26383 <1> ; 07/02/2022 26384 00005449 8F05[C06C0000] <1> pop dword [u.namep] ; directory name 26385 <1> 26386 <1> ; 09/05/2022 - Retro UNIX v1.2 (Kernel v0.2.2.1) 26387 <1> ; (root fs/device must not be mounted again) 26388 0000544F 3A05[826C0000] <1> cmp al, [rdev] 26389 <1> ;je sysmnt_err0 26390 00005455 74E7 <1> je short sysmnt_0_err ; permission denied error 26391 <1> 26392 <1> ; 13/10/2015 26393 <1> ;movzx ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5) 26394 <1> ; 11/01/2022 26395 00005457 29DB <1> sub ebx, ebx 26396 00005459 88C3 <1> mov bl, al 26397 0000545B F683[AE620000]80 <1> test byte [ebx+drv.status], 80h ; 24/10/2015 26398 00005462 750F <1> jnz short sysmnt_1 26399 <1> sysmnt_err1: 26400 00005464 C705[186D0000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY ; drive not ready ! 26401 0000546C 0000 <1> 26402 0000546E E9F2DCFFFF <1> jmp error 26403 <1> sysmnt_1: 26404 <1> ; 07/02/2022 26405 <1> ;pop dword [u.namep] 26406 <1> ; mov (sp)+,u.namep / put the name of file to be placed 26407 <1> ; / on the device 26408 <1> ; 14/11/2015 26409 00005473 53 <1> push ebx ; 13/10/2015 26410 <1> ; mov r1,-(sp) / save the device number 26411 <1> ; 26412 00005474 E803ECFFFF <1> call namei 26413 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 26414 <1> ; ax = 0 -> file not found 26415 <1> ;jz error 26416 <1> ;jc error 26417 <1> ; jsr r0,namei / get the i-number of the file 26418 <1> ; br errora 26419 00005479 730F <1> jnc short sysmnt_2 26420 <1> sysmnt_err2: 26421 0000547B C705[186D0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready ! 26422 00005483 0000 <1> 26423 00005485 E9DBDCFFFF <1> jmp error 26424 <1> sysmnt_2: 26425 <1> ; 11/01/2022 26426 0000548A A3[8A6C0000] <1> mov [mnti], eax ; 32 bit inode number (<= 65535) 26427 <1> ;mov [mnti], ax 26428 <1> ; mov r1,mnti / put it in mnti 26429 <1> 26430 <1> ; 15/05/2022 26431 <1> ; -Retro UNIX 8086/386 v1 feaure only- 26432 0000548F A1[7C6C0000] <1> mov eax, [ii] 26433 00005494 A3[8E6C0000] <1> mov [mntp], eax ; parent dir inumber of [mnti] 26434 <1> 26435 <1> ; 11/01/2022 26436 00005499 BB[546F0000] <1> mov ebx, sb1 ; super block buffer header (of mounted disk) 26437 <1> sysmnt_3: ;1: 26438 <1> ;cmp byte [ebx+1], 0 26439 <1> ; tstb sb1+1 / is 15th bit of I/O queue entry for 26440 <1> ; / dismountable device set? 26441 <1> ;jna short sysmnt_4 26442 <1> ; bne 1b / (inhibit bit) yes, skip writing 26443 <1> ;call idle ; (wait for hardware interrupt) 26444 <1> ;jmp short sysmnt_3 26445 <1> sysmnt_4: 26446 0000549E 58 <1> pop eax ; Retro UNIX 8086 v1 device number/ID (0 to 5) 26447 0000549F A2[836C0000] <1> mov [mdev], al 26448 <1> ; mov (sp),mntd / no, put the device number in mntd 26449 000054A4 8803 <1> mov [ebx], al 26450 <1> ; movb (sp),sb1 / put the device number in the lower byte 26451 <1> ; / of the I/O queue entry 26452 <1> ;mov byte [cdev], 1 ; mounted device/drive 26453 <1> ; mov (sp)+,cdev / put device number in cdev 26454 000054A6 66810B0004 <1> or word [ebx], 400h ; Bit 10, 'read' flag/bit 26455 <1> ; bis $2000,sb1 / set the read bit 26456 <1> 26457 <1> ; 09/05/2022 26458 000054AB 31FF <1> xor edi, edi 26459 000054AD 897B04 <1> mov dword [ebx+4], edi ; 0 ; physical block number = 0 26460 <1> 26461 <1> ; 09/05/2022 26462 <1> ; Retro UNIX v2 Hard Disk FS recognition. 26463 <1> ; 26464 000054B0 3C02 <1> cmp al, 2 ; fd0 = 0, fd1 = 1, hd0 = 2, hd1 = 3 26465 000054B2 7217 <1> jb short sysmnt_8 26466 <1> 26467 <1> ; hard disk, read masterboot sector/block at first 26468 000054B4 E817060000 <1> call diskio 26469 000054B9 721A <1> jc short sysmnt_9 ; disk read error ! 26470 <1> sysmnt_6: 26471 <1> ; return start sector address of 26472 <1> ; retro unix v2 partition in esi 26473 000054BB 8D7308 <1> lea esi, [ebx+8] ; (mbr buffer data address) 26474 000054BE E869DBFFFF <1> call runix_p_bs 26475 000054C3 7206 <1> jc short sysmnt_8 ; runix partition not found 26476 <1> ; try to read superblock on 26477 <1> ; physical sector 1 26478 <1> ; eax = start sector/block 26479 000054C5 894304 <1> mov dword [ebx+4], eax ; (boot sector address) 26480 <1> ; esi = partition table entry + 4 26481 000054C8 8B7E08 <1> mov edi, [esi+ptSectors-ptFileSystemID] 26482 <1> ; edi = partition size in sectors 26483 <1> sysmnt_8: 26484 <1> ; Retro UNIX 386 v1 modification : 26485 <1> ; 32 bit block number at buffer header offset 4 26486 <1> ; 09/05/2022 26487 <1> ;mov dword [ebx+4], 1 ; physical block number = 1 26488 000054CB FF4304 <1> inc dword [ebx+4] ; +1 ; superblock address 26489 000054CE E8FD050000 <1> call diskio 26490 000054D3 7345 <1> jnc short sysmnt_5 26491 <1> sysmnt_9: 26492 000054D5 31C0 <1> xor eax, eax 26493 000054D7 66A3[8A6C0000] <1> mov [mnti], ax ; 0 26494 000054DD A2[836C0000] <1> mov [mdev], al ; 0 26495 <1> ;mov [cdev], al ; 0 26496 <1> ; 08/02/2022 26497 000054E2 803D[176D0000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 26498 000054E9 7508 <1> jne short sysmnt_err3 26499 <1> ; yes, clear [u.brwdev] for next check 26500 <1> ; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 26501 000054EB FE05[176D0000] <1> inc byte [u.brwdev] ; 0, reset 26502 000054F1 EB0A <1> jmp short sysmnt_err4 26503 <1> sysmnt_err3: ; 08/02/2022 26504 <1> ; no, set [u.error] to disk read error 26505 000054F3 C705[186D0000]1100- <1> mov dword [u.error], ERR_DRV_READ ; 'disk read error !' 26506 000054FB 0000 <1> 26507 <1> sysmnt_err4: 26508 <1> ; 08/02/2022 26509 <1> ; 14/11/2015 26510 000054FD FEC8 <1> dec al 26511 000054FF 8903 <1> mov [ebx], eax ; 000000FFh 26512 00005501 FEC0 <1> inc al 26513 00005503 48 <1> dec eax 26514 00005504 894304 <1> mov [ebx+4], eax ; 0FFFFFFFFh 26515 00005507 E959DCFFFF <1> jmp error 26516 <1> sysmnt_invd: 26517 <1> ; 08/02/2022 26518 0000550C C705[186D0000]1C00- <1> mov dword [u.error], ERR_INV_FS ; 28 26519 00005514 0000 <1> 26520 <1> ;'invalid fs/superblock !' error 26521 00005516 30C0 <1> xor al, al ; 0 26522 00005518 EBE3 <1> jmp short sysmnt_err4 26523 <1> 26524 <1> sysmnt_5: 26525 <1> ; 09/05/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.1) 26526 <1> ; Retro UNIX v2 Hard Disk FS recognition. 26527 <1> ; edi = 0 -> diskette or 'not a runix v2 hdfs partition' 26528 <1> ; edi > 0 -> retro unix v2 hdfs partition (volume) size 26529 <1> ; in sectors 26530 <1> 26531 0000551A 21FF <1> and edi, edi 26532 0000551C 740D <1> jz short sysmnt_10 26533 <1> 26534 0000551E 8B530C <1> mov edx, [ebx+12] ; SB.BootSectAddr (Hidden Sectors) 26535 00005521 42 <1> inc edx ; +1 26536 00005522 3B5304 <1> cmp edx, [ebx+4] ; superblock (disk) address 26537 00005525 75E5 <1> jne short sysmnt_invd ; invalid file system ! 26538 <1> 26539 00005527 89F9 <1> mov ecx, edi ; volume size (from partition table entry) 26540 00005529 EB0C <1> jmp short sysmnt_11 ; bypass disk size comparison 26541 <1> 26542 <1> sysmnt_10: 26543 <1> ; 08/02/2022 26544 <1> ; 11/01/2022 (Retro UNIX 386 v1.1 BugFix) 26545 <1> ; v1.2 Note: This code will be changed for hard disk partitions 26546 <1> ; ! (for now, rufs v2 floppy disks can be mounted) ! 26547 <1> ; 14/11/2015 (Retro UNIX 386 v1 modification) 26548 <1> ; (Following check is needed to prevent mounting an 26549 <1> ; invalid file system (invalid super block). 26550 <1> ; 26551 0000552B 0FB603 <1> movzx eax, byte [ebx] ; device number 26552 0000552E C0E002 <1> shl al, 2 ; 4*index 26553 00005531 8B88[92620000] <1> mov ecx, [eax+drv.size] ; volume (fs) size 26554 <1> ;shr ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte) 26555 <1> ; ecx = number of free map bytes (required) 26556 <1> ;;movzx edx, word [sb1+8] ; the 1st data word ('mount:') 26557 <1> ;movzx edx, word [ebx+8] ; the 1st data word (of the buffer) 26558 <1> ; edx = number of free blocks map bytes 26559 <1> ;;shl edx, 3 ; convert free map bytes to free map bits 26560 <1> ;cmp ecx, edx ; compare free map bits and volume size 26561 <1> ; ; (in sectors), if they are not equal 26562 <1> ; ; the disk to be mounted is an... 26563 <1> ;jne short sysmnt_invd ; invalid disk ! 26564 <1> ; ; (which has not got a valid super block) 26565 <1> sysmnt_11: 26566 <1> ; 07/02/2022 26567 <1> ;xor al, al ; 08/02/2022 26568 <1> ; 11/01/2022 26569 <1> ; Retro UNIX 386 v2 superblock (offset 8, volume size) 26570 00005537 8B5310 <1> mov edx, [ebx+16] ; SB.VolumeSize (in sectors) 26571 0000553A 39D1 <1> cmp ecx, edx ; compare SB.VolumeSize and Disk volume size 26572 <1> ; (in sectors), if they are not equal 26573 <1> ; the disk to be mounted is an... 26574 0000553C 75CE <1> jne short sysmnt_invd ; invalid disk ! 26575 <1> ; (which has not got a valid shuper block) 26576 <1> ; 26577 0000553E C6430100 <1> mov byte [ebx+1], 0 26578 <1> ; jsr r0,ppoke / read in entire file system 26579 <1> ;sysmnt_6: ;1: 26580 <1> ;;cmp byte [sb1+1], 0 26581 <1> ; tstb sb1+1 / done reading? 26582 <1> ;;jna sysret 26583 <1> ;;call idle ; (wait for hardware interrupt) 26584 <1> ;;jmp short sysmnt_6 26585 <1> ;bne 1b / no, wait 26586 <1> ;br sysreta / yes 26587 00005542 E93EDCFFFF <1> jmp sysret 26588 <1> 26589 <1> sysumount: ; / special dismount file system 26590 <1> ; 15/05/2022 26591 <1> ; 09/05/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.1) 26592 <1> ; 11/01/2022 (Retro UNIX 386 v1.2) 26593 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 26594 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 26595 <1> ; 26596 <1> ; 04/11/2013 26597 <1> ; 09/07/2013 26598 <1> ; 'sysumount' anounces to the system that the special file, 26599 <1> ; indicated as an argument is no longer contain a removable 26600 <1> ; file system. 'getspl' gets the device number of the special 26601 <1> ; file. If no file system was mounted on that device an error 26602 <1> ; occurs. 'mntd' and 'mnti' are cleared and control is passed 26603 <1> ; to 'sysret'. 26604 <1> ; 26605 <1> ; Calling sequence: 26606 <1> ; sysmount; special 26607 <1> ; Arguments: 26608 <1> ; special - special file to dismount (device) 26609 <1> ; 26610 <1> ; Inputs: - 26611 <1> ; Outputs: - 26612 <1> ; ............................................................... 26613 <1> ; 26614 <1> ; Retro UNIX 8086 v1 modification: 26615 <1> ; 'sysumount' system call has one argument; so, 26616 <1> ; * Single argument, special is pointed to by BX register 26617 <1> ; 26618 <1> 26619 <1> ;mov ax, 1 ; one/single argument, put argument in BX 26620 <1> ;call arg 26621 <1> ; jsr r0,arg; u.namep / point u.namep to special 26622 00005547 891D[C06C0000] <1> mov [u.namep], ebx 26623 0000554D E86C000000 <1> call getspl 26624 <1> ; jsr r0,getspl / get the device number in r1 26625 <1> ;;; 26626 <1> ; 09/05/2022 - Erdogan Tan 26627 <1> ; (I have added [mnti] check because 26628 <1> ; retro unix device number of /dev/fd0 is 0 26629 <1> ; .. so, 'cmp al, [mdev]' is not enough 26630 <1> ; for dismounting /dev/fd0. sysumount system call would give 26631 <1> ; wrong cf=0 result while /dev/fd0 is not mounted.) 26632 00005552 66833D[8A6C0000]00 <1> cmp word [mnti], 0 26633 0000555A 767A <1> jna short sysmnt_err0 ; there is not a mounted device ! 26634 <1> ;;; 26635 <1> 26636 0000555C 3A05[836C0000] <1> cmp al, [mdev] 26637 <1> ; cmp r1,mntd / is it equal to the last device mounted? 26638 00005562 7572 <1> jne short sysmnt_err0 ; 'permission denied !' error 26639 <1> ;jne error 26640 <1> ; bne errora / no error 26641 00005564 30C0 <1> xor al, al ; ah = 0 26642 <1> ; (eax = 0) ; 11/01/2022 26643 <1> sysumnt_0: ;1: 26644 <1> ; 11/01/2022 26645 <1> ;cmp [sb1+1], al ; 0 26646 <1> ; ; tstb sb1+1 / yes, is the device still doing I/O 26647 <1> ; ; / (inhibit bit set)? 26648 <1> ;jna short sysumnt_1 26649 <1> ; ; bne 1b / yes, wait 26650 <1> ;call idle ; (wait for hardware interrupt) 26651 <1> ;jmp short sysumnt_0 26652 <1> sysumnt_1: 26653 <1> ; 15/05/2022 26654 <1> ; change user's current directory to mounting directory 26655 <1> ; if it is on the mounted device (chdir back to root fs) 26656 00005566 3805[AC6C0000] <1> cmp byte [u.cdrv], al ; 0 26657 0000556C 7641 <1> jna short sysumnt_4 26658 <1> ;;; 26659 <1> ; 15/05/2022 26660 <1> ; It is needed to change the parent process's current 26661 <1> ; directory because shell runs (/etc/umount) 26662 <1> ; as child process. 26663 0000556E 31DB <1> xor ebx, ebx 26664 00005570 8A1D[F56C0000] <1> mov bl, [u.uno] 26665 00005576 D0E3 <1> shl bl, 1 ; >= 2 .. <= 32 26666 00005578 81C3[82680000] <1> add ebx, p.ppid-2 26667 0000557E 668B13 <1> mov dx, [ebx] ; process id of the parent [p.ppid] 26668 00005581 BE[64680000] <1> mov esi, p.pid 26669 00005586 29C9 <1> sub ecx, ecx 26670 00005588 B110 <1> mov cl, nproc ; 16 26671 <1> sysumnt_2: 26672 0000558A 66AD <1> lodsw 26673 0000558C 6639D0 <1> cmp ax, dx 26674 0000558F 7402 <1> je short sysumnt_3 26675 00005591 E2F7 <1> loop sysumnt_2 26676 <1> sysumnt_3: 26677 00005593 31C0 <1> xor eax, eax 26678 00005595 81EE[64680000] <1> sub esi, p.pid 26679 0000559B D1E6 <1> shl esi, 1 26680 0000559D 8B9E[D0680000] <1> mov ebx, [esi+p.upage-4] ; the parent's upage 26681 <1> ; ebx points to user (u) structure in upage 26682 000055A3 8B15[8A6C0000] <1> mov edx, [mnti] ; * (32 bit inumber but < 65536) 26683 <1> ;mov [u.cdir], dx 26684 <1> ;mov [u.cdrv], al ; 0 26685 000055A9 89530C <1> mov [ebx+u.cdir-user], edx 26686 <1> ; * (32 bit inumber but < 65536) 26687 000055AC 884310 <1> mov [ebx+u.cdrv-user], al ; 0 26688 <1> ;;; 26689 <1> sysumnt_4: 26690 000055AF A2[836C0000] <1> mov [mdev], al ; 0 26691 <1> ; clr mntd / no, clear these 26692 000055B4 A3[8A6C0000] <1> mov [mnti], eax ; 11/01/2022 (eax = 0) 26693 <1> ;mov [mnti], ax ; 0 26694 <1> ; clr mnti 26695 <1> 26696 <1> ;; 15/05/2022 26697 <1> ;mov [cdev], al ; 0 ; [u.cdrv] = 0 26698 <1> ;mov eax, edx ; [u.cdir] 26699 <1> ;call iget 26700 <1> 26701 000055B9 E9C7DBFFFF <1> jmp sysret 26702 <1> ; br sysreta / return 26703 <1> 26704 <1> ; 11/01/2022 - Retro UNIX 386 v1.2 26705 <1> ; (runix v2 fs inode numbers) 26706 <1> getspl: ; / get device number from a special file name 26707 000055BE E8B9EAFFFF <1> call namei 26708 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 26709 <1> ; ax = 0 -> file not found 26710 <1> ;jc sysmnt_err2 ; 'file not found !' error 26711 <1> ; 11/01/2022 (Retro UNIX 386 v1.2) 26712 000055C3 7305 <1> jnc short getspl_0 26713 000055C5 E9B1FEFFFF <1> jmp sysmnt_err2 26714 <1> getspl_0: 26715 <1> ;jz error 26716 <1> ;jc error 26717 <1> ; jsr r0,namei / get the i-number of the special file 26718 <1> ; br errora / no such file 26719 <1> ; 11/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode numbers) 26720 000055CA 6683E80A <1> sub ax, 10 ; fd0 inode number = 10, hd3 inode number = 15 26721 <1> ; i-number-10, 0 = fd0, 5 = hd3 26722 <1> ;sub ax, 3 ; Retro UNIX 8086 v1 modification ! 26723 <1> ; i-number-3, 0 = fd0, 5 = hd3 26724 <1> ; sub $4,r1 / i-number-4 rk=1,tap=2+n 26725 000055CE 7206 <1> jc short sysmnt_err0 ; 'permission denied !' error 26726 <1> ;jc error 26727 <1> ; ble errora / less than 0? yes, error 26728 000055D0 6683F805 <1> cmp ax, 5 ; 5 = hd3 26729 <1> ; cmp r1,$9. / greater than 9 tap 7 26730 <1> ;ja short sysmnt_err0 ; 'permission denied !' error 26731 <1> ;;ja error 26732 <1> ; bgt errora / yes, error 26733 <1> ; 11/01/2022 26734 000055D4 760F <1> jna short getspl_retn 26735 <1> ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 26736 <1> ;iopen_retn: 26737 <1> ; retn 26738 <1> ; rts r0 / return with device number in r1 26739 <1> sysmnt_err0: 26740 000055D6 C705[186D0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 26741 000055DE 0000 <1> 26742 000055E0 E980DBFFFF <1> jmp error 26743 <1> 26744 <1> getspl_retn: 26745 <1> ; 11/01/2022 26746 <1> ; eax = Retro UNIX 386 v1 device number (0 to 5) 26747 <1> iopen_retn: 26748 000055E5 C3 <1> retn 26749 <1> 26750 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 26751 <1> ; (Printer initialization) 26752 <1> ; 11/02/2022 26753 <1> ; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification 26754 <1> iopen: 26755 <1> ; 05/12/2021 - Retro UNIX 386 v1.2 26756 <1> ; 27/03/2021 (Retro UNIX 386 v2) 26757 <1> ; 19/05/2015 26758 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 26759 <1> ; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1) 26760 <1> ; 26761 <1> ; open file whose i-number is in r1 26762 <1> ; 26763 <1> ; INPUTS -> 26764 <1> ; r1 - inode number 26765 <1> ; OUTPUTS -> 26766 <1> ; file's inode in core 26767 <1> ; r1 - inode number (positive) 26768 <1> ; 26769 <1> ; ((AX = R1)) 26770 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 26771 <1> ; 26772 <1> ; / open file whose i-number is in r1 26773 <1> ; test ah, 80h ; Bit 15 of AX 26774 <1> ; ; tst r1 / write or read access? 26775 <1> ; jnz short iopen_2 26776 <1> ; ; blt 2f / write, go to 2f 26777 <1> ; mov dl, 2 ; read access 26778 <1> ; call access 26779 <1> ; ; jsr r0,access; 2 26780 <1> ; ; / get inode into core with read access 26781 <1> ; ; DL=2 26782 <1> ;iopen_0: 26783 <1> ; cmp ax, 40 26784 <1> ; ; cmp r1,$40. / is it a special file 26785 <1> ; ja short iopen_retn 26786 <1> ; ; bgt 3f / no. 3f 26787 <1> 26788 <1> ; 05/12/2021 26789 <1> ; DL = 0 -> open for read 26790 <1> ; DL = 1 -> open for write 26791 <1> ; 11/02/2022 26792 <1> ; DL = 2 -> create (open for write) 26793 <1> ; (caller: syscreat) 26794 <1> 26795 000055E6 52 <1> push edx ; * 26796 <1> 26797 <1> ; set permission/mode flag for 'access' 26798 <1> ; (DX = 100h -> IREAD, DX = 80h -> IWRITE) 26799 <1> 26800 000055E7 B601 <1> mov dh, 1 26801 000055E9 08D2 <1> or dl, dl ; dl = 0, open for read 26802 000055EB 7404 <1> jz short iopen_0 ; DX = IREAD (100h) 26803 <1> ; dl = 1, open for write 26804 <1> ; or 26805 <1> ; dl = 2, create (regular) file ; 11/02/2022 26806 000055ED FECE <1> dec dh 26807 000055EF B280 <1> mov dl, 80h 26808 <1> ; DX = IWRITE (80h) 26809 <1> iopen_0: 26810 <1> ; 27/03/2021 26811 <1> ; EAX = inode number (in AX) 26812 <1> ; DX = access mode, 100h = read, 80h = write 26813 <1> 26814 <1> ; 24/06/2020 - Retro UNIX 386 v2 26815 000055F1 E869F6FFFF <1> call access 26816 <1> ; jsr r0,access; 1 / get inode in core 26817 <1> 26818 <1> ; 27/03/2021 26819 <1> ; DX return value from 'access' subroutine 26820 <1> ; may be 100h, 20h, 04h for DX = 100h (IREAD) input 26821 <1> ; 80h, 10h, 02h for DX = 80h (IWRITE) input 26822 <1> 26823 <1> ; 05/12/2021 26824 000055F6 5A <1> pop edx ; * ; dl = 0 -> open for read 26825 <1> ; dl = 1 -> open for write 26826 <1> ; 11/02/2022 26827 <1> ; dl = 2 -> create (regular) file 26828 <1> ; (open for writing) 26829 <1> ; 24/06/2020 26830 000055F7 8A0D[25680000] <1> mov cl, [i.flgs+1] 26831 <1> 26832 000055FD F6C180 <1> test cl, 80h ; regular file ? 26833 00005600 7525 <1> jnz short iopen_1 ; yes ; 05/12/2021 26834 00005602 F6C120 <1> test cl, 20h ; device file ? 26835 <1> ;jnz short iopen_2 ; yes 26836 <1> ; 11/02/2022 26837 00005605 7414 <1> jz short iopen_invf ; no, invalid file/inode ! 26838 <1> ; device file/inode 26839 00005607 F6C202 <1> test dl, 2 ; create file ? 26840 0000560A 7425 <1> jz short iopen_2 ; device file r/w (dl=0 or dl=1) 26841 <1> ; an attempt to create a file 26842 <1> ; whith name of existing device file in same directory! 26843 <1> iopen_pdnd: 26844 0000560C C705[186D0000]0B00- <1> mov dword [u.error], ERR_PERM_DENIED ; 11 26845 00005614 0000 <1> 26846 <1> ; 'permission denied !' error 26847 <1> iopen_err: 26848 00005616 E94ADBFFFF <1> jmp error 26849 <1> iopen_invf: 26850 <1> ; invalid inode (flags) 26851 0000561B C705[186D0000]FF00- <1> mov dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file 26852 00005623 0000 <1> 26853 00005625 EBEF <1> jmp short iopen_err 26854 <1> 26855 <1> iopen_1: 26856 <1> ; 05/12/2021 26857 <1> ; (If open mode is 'write' and the file/inode is a directory, 26858 <1> ; open request will/must be rejected.) 26859 <1> ; 26860 <1> ; (If inode is a regular file and it is not a directory, 26861 <1> ; there is nothing to do here, we need to return to 'sysopen' 26862 <1> ; for completing the rest of file opening procedure.) 26863 <1> 26864 00005627 F6C140 <1> test cl, 40h ; directory ? 26865 0000562A 74B9 <1> jz short iopen_retn ; no 26866 <1> 26867 0000562C 20D2 <1> and dl, dl ; open mode is 1 (write) 26868 <1> ;jz short iopen_retn ; no 26869 <1> ; 11/02/2022 26870 <1> ; open mode 1 (write) or 2 (create) 26871 0000562E 75DC <1> jnz short iopen_pdnd ; 'permission denied !' error 26872 <1> ;iopen_retn: 26873 00005630 C3 <1> retn 26874 <1> 26875 <1> ; !!! 26876 <1> ; 'sysopen' for writing 26877 <1> ; is not applicable for directories 26878 <1> ; (Directory entries must be created or deleted by 26879 <1> ; relevant system calls.) 26880 <1> 26881 <1> ;;mov dword [u.error], ERR_DIR_ACCESS ; 11 26882 <1> ;mov dword [u.error], ERR_PERM_DENIED ; 11 26883 <1> ; ; 'permission denied !' error 26884 <1> ;;jmp error 26885 <1> ;jmp short iopen_err 26886 <1> 26887 <1> ;iopen_retn: 26888 <1> ; retn 26889 <1> 26890 <1> iopen_2: 26891 <1> ;push ax 26892 <1> ; ; mov r1,-(sp) / yes, figure out 26893 <1> ;movzx ebx, al 26894 <1> ;shl bx, 2 26895 <1> ; ; asl r1 26896 <1> ;add ebx, iopen_1 - 4 26897 <1> ;jmp dword [ebx] 26898 <1> ; ; jmp *1f-2(r1) / which one and transfer to it 26899 <1> 26900 <1> ; 05/12/2021 26901 00005631 50 <1> push eax ; save inode number 26902 <1> ; device file 26903 00005632 BB[4E560000] <1> mov ebx, iopen_4 26904 00005637 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 26905 0000563A 720E <1> jb short iopen_3 ; null 26906 0000563C 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 26907 0000563F 7709 <1> ja short iopen_3 ; null 26908 <1> ; convert v2 inode number to v1 device inode number 26909 00005641 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 26910 00005643 89C1 <1> mov ecx, eax 26911 00005645 C0E102 <1> shl cl, 2 ; * 4 26912 00005648 01CB <1> add ebx, ecx 26913 <1> iopen_3: 26914 0000564A FEC2 <1> inc dl ; 1 = read, 2 = write 26915 0000564C FF23 <1> jmp dword [ebx] 26916 <1> ; jmp *1f-2(r1) 26917 <1> ;iopen_1: ; 1: 26918 <1> iopen_4: 26919 0000564E [7E4F0000] <1> dd null ; 05/12/2021 26920 00005652 [9E560000] <1> dd otty ; tty, AX = 1 (runix) 26921 <1> ;otty / tty ; r1=2 26922 <1> ;oppt / ppt ; r1=4 26923 00005656 [56570000] <1> dd sret ; mem, AX = 2 (runix) 26924 <1> ;sret / mem ; r1=6 26925 <1> ;sret / rf0 26926 <1> ;sret / rk0 26927 <1> ;sret / tap0 26928 <1> ;sret / tap1 26929 <1> ;sret / tap2 26930 <1> ;sret / tap3 26931 <1> ;sret / tap4 26932 <1> ;sret / tap5 26933 <1> ;sret / tap6 26934 <1> ;sret / tap7 26935 0000565A [56570000] <1> dd sret ; fd0, AX = 3 (runix only) 26936 0000565E [56570000] <1> dd sret ; fd1, AX = 4 (runix only) 26937 00005662 [56570000] <1> dd sret ; hd0, AX = 5 (runix only) 26938 00005666 [56570000] <1> dd sret ; hd1, AX = 6 (runix only) 26939 0000566A [56570000] <1> dd sret ; hd2, AX = 7 (runix only) 26940 0000566E [56570000] <1> dd sret ; hd3, AX = 8 (runix only) 26941 <1> ;;dd error ; lpr, AX = 9 (error !) 26942 <1> ;dd sret ; lpr, AX = 9 (runix) 26943 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 (lpt_init) 26944 00005672 [32580000] <1> dd ejec ; lpr, AX = 9 (runix) 26945 00005676 [AF560000] <1> dd ocvt ; tty0, AX = 10 (runix) 26946 <1> ;ocvt / tty0 26947 0000567A [AF560000] <1> dd ocvt ; tty1, AX = 11 (runix) 26948 <1> ;ocvt / tty1 26949 0000567E [AF560000] <1> dd ocvt ; tty2, AX = 12 (runix) 26950 <1> ;ocvt / tty2 26951 00005682 [AF560000] <1> dd ocvt ; tty3, AX = 13 (runix) 26952 <1> ;ocvt / tty3 26953 00005686 [AF560000] <1> dd ocvt ; tty4, AX = 14 (runix) 26954 <1> ;ocvt / tty4 26955 0000568A [AF560000] <1> dd ocvt ; tty5, AX = 15 (runix) 26956 <1> ;ocvt / tty5 26957 0000568E [AF560000] <1> dd ocvt ; tty6, AX = 16 (runix) 26958 <1> ;ocvt / tty6 26959 00005692 [AF560000] <1> dd ocvt ; tty7, AX = 17 (runix) 26960 <1> ;ocvt / tty7 26961 00005696 [AF560000] <1> dd ocvt ; COM1, AX = 18 (runix only) 26962 <1> ;error / crd 26963 0000569A [AF560000] <1> dd ocvt ; COM2, AX = 19 (runix only) 26964 <1> 26965 <1> ;iopen_2: ; 2: / check open write access 26966 <1> ; neg ax 26967 <1> ; ; neg r1 / make inode number positive 26968 <1> ; mov dl, 1 ; write access 26969 <1> ; call access 26970 <1> ; ; jsr r0,access; 1 / get inode in core 26971 <1> ; ; DL=1 26972 <1> ; test word [i.flgs], 4000h ; Bit 14 : Directory flag 26973 <1> ; ;bit $40000,i.flgs / is it a directory? 26974 <1> ; jz short iopen_0 26975 <1> ; ;mov [u.error], ERR_DIR_ACCESS 26976 <1> ; ;jmp error ; permission denied ! 26977 <1> ; jmp sysmnt_err0 26978 <1> ; ;;jnz error 26979 <1> ; ; bne 2f / yes, transfer (error) 26980 <1> ; ;;jmp short iopen_0 26981 <1> ; ;cmp ax, 40 26982 <1> ; ; cmp r1,$40. / no, is it a special file? 26983 <1> ; ;ja short iopen_2 26984 <1> ; ; bgt 3f / no, return 26985 <1> ; ;push ax 26986 <1> ; ; mov r1,-(sp) / yes 26987 <1> ; ;movzx ebx, al 26988 <1> ; ;shl bx, 1 26989 <1> ; ; asl r1 26990 <1> ; ;add ebx, ipen_3 - 2 26991 <1> ; ;jmp dword [ebx] 26992 <1> ; ; jmp *1f-2(r1) / figure out 26993 <1> ; ; / which special file it is and transfer 26994 <1> ;iopen_3: ; 1: 26995 <1> ; dd otty ; tty, AX = 1 (runix) 26996 <1> ; ;otty / tty ; r1=2 26997 <1> ; ;leadr / ppt ; r1=4 26998 <1> ; dd sret ; mem, AX = 2 (runix) 26999 <1> ; ;sret / mem ; r1=6 27000 <1> ; ;sret / rf0 27001 <1> ; ;sret / rk0 27002 <1> ; ;sret / tap0 27003 <1> ; ;sret / tap1 27004 <1> ; ;sret / tap2 27005 <1> ; ;sret / tap3 27006 <1> ; ;sret / tap4 27007 <1> ; ;sret / tap5 27008 <1> ; ;sret / tap6 27009 <1> ; ;sret / tap7 27010 <1> ; dd sret ; fd0, AX = 3 (runix only) 27011 <1> ; dd sret ; fd1, AX = 4 (runix only) 27012 <1> ; dd sret ; hd0, AX = 5 (runix only) 27013 <1> ; dd sret ; hd1, AX = 6 (runix only) 27014 <1> ; dd sret ; hd2, AX = 7 (runix only) 27015 <1> ; dd sret ; hd3, AX = 8 (runix only) 27016 <1> ; dd sret ; lpr, AX = 9 (runix) 27017 <1> ; ;dd ejec ; lpr, AX = 9 (runix) 27018 <1> ; dd sret ; tty0, AX = 10 (runix) 27019 <1> ; ;ocvt / tty0 27020 <1> ; dd sret ; tty1, AX = 11 (runix) 27021 <1> ; ;ocvt / tty1 27022 <1> ; dd sret ; tty2, AX = 12 (runix) 27023 <1> ; ;ocvt / tty2 27024 <1> ; dd sret ; tty3, AX = 13 (runix) 27025 <1> ; ;ocvt / tty3 27026 <1> ; dd sret ; tty4, AX = 14 (runix) 27027 <1> ; ;ocvt / tty4 27028 <1> ; dd sret ; tty5, AX = 15 (runix) 27029 <1> ; ;ocvt / tty5 27030 <1> ; dd sret ; tty6, AX = 16 (runix) 27031 <1> ; ;ocvt / tty6 27032 <1> ; dd sret ; tty7, AX = 17 (runix) 27033 <1> ; ;ocvt / tty7 27034 <1> ; dd ocvt ; COM1, AX = 18 (runix only) 27035 <1> ; ;/ ejec / lpr 27036 <1> ; dd ocvt ; COM2, AX = 19 (runix only) 27037 <1> 27038 <1> otty: ;/ open console tty for reading or writing 27039 <1> ; 03/03/2022 27040 <1> ; 23/02/2022 27041 <1> ; 22/02/2022 27042 <1> ; 09/02/2022 27043 <1> ; 06/02/2022 27044 <1> ; 08/01/2022 27045 <1> ; 01/01/2022 27046 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 27047 <1> ; 16/11/2015 27048 <1> ; 12/11/2015 27049 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 27050 <1> ; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1) 27051 <1> ; 16/07/2013 27052 <1> ; Retro UNIX 8086 v1 modification: 27053 <1> ; If a tty is open for read or write by 27054 <1> ; a process (u.uno), only same process can open 27055 <1> ; same tty to write or read (R->R&W or W->W&R). 27056 <1> ; 27057 <1> ; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty) 27058 <1> ; 27059 <1> 27060 0000569E 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 27061 000056A5 8A83[A3680000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 27062 <1> ; 13/01/2014 27063 <1> ;jmp short ottyp 27064 <1> ; 23/02/2022 27065 000056AB 88C4 <1> mov ah, al 27066 <1> ; 06/02/2022 27067 000056AD EB06 <1> jmp short otty_0 27068 <1> ocvt: 27069 000056AF 2C0A <1> sub al, 10 27070 <1> ;ottyp: ; (call from sysstty) 27071 <1> ; 08/01/2022 27072 000056B1 31DB <1> xor ebx, ebx 27073 <1> ottyp: ; 03/03/2022 27074 <1> ; (ebx < 256) ; 06/02/2022 27075 <1> ; 23/02/2022 27076 000056B3 B4FF <1> mov ah, 0FFh 27077 <1> ; 22/02/2022 27078 <1> otty_0: 27079 <1> ; 09/02/2022 27080 <1> ; INPUT: 27081 <1> ; DL=1 for read, DL=2 for write, DL=0 for sysstty 27082 <1> ; 27083 <1> ; 08/01/2022 27084 <1> ; 01/01/2022 27085 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 27086 <1> ; 16/11/2015 27087 <1> ; 12/11/2015 27088 <1> ; 18/05/2015 (32 bit modifications) 27089 <1> ; 06/12/2013 - 13/07/2014 27090 000056B5 88C6 <1> mov dh, al ; tty number 27091 <1> ;movzx ebx, al ; AL = tty number (0 to 9), AH = 0 27092 <1> ; 08/01/2022 27093 000056B7 88C3 <1> mov bl, al 27094 000056B9 D0E3 <1> shl bl, 1 ; aligned to word 27095 <1> ; 26/01/2014 27096 000056BB 81C3[B4670000] <1> add ebx, ttyl 27097 000056C1 668B0B <1> mov cx, [ebx] 27098 <1> ; CL = lock value (0 or process number) 27099 <1> ; CH = open count 27100 000056C4 20C9 <1> and cl, cl 27101 <1> ; 13/01/2014 27102 <1> ;jz short otty_ret 27103 <1> ; 05/12/2021 27104 000056C6 7447 <1> jz short ottys_0 27105 <1> ; 27106 <1> ; 16/11/2015 27107 000056C8 3A0D[F56C0000] <1> cmp cl, [u.uno] 27108 000056CE 746E <1> je short ottys_3 27109 <1> ; 27110 <1> ; 23/02/2022 27111 <1> ; (is it the console tty of the current process?) 27112 <1> ; ((fast check/permit for console tty open function)) 27113 000056D0 38E0 <1> cmp al, ah ; cmp dh, ah 27114 000056D2 746A <1> je short ottys_3 ; bypass parent process check 27115 <1> ; 27116 <1> ; 27117 <1> ; 22/02/2022 27118 <1> ;movzx ebx, cl ; the process which has locked the tty 27119 <1> ;shl bl, 1 27120 <1> ;mov ax, [ebx+p.pid-2] 27121 <1> ;;movzx ebx, byte [u.uno] 27122 <1> ;mov bl, [u.uno] 27123 <1> ;shl bl, 1 27124 <1> ;cmp ax, [ebx+p.ppid-2] 27125 <1> ;je short ottys_3 ; 16/11/2015 27126 <1> ; 22/02/2022 (BugFix) ; * 27127 000056D4 0FB6F1 <1> movzx esi, cl ; the process which has locked the tty 27128 000056D7 D1E6 <1> shl esi, 1 27129 000056D9 668B86[62680000] <1> mov ax, [esi+p.pid-2] 27130 000056E0 96 <1> xchg esi, eax 27131 000056E1 A0[F56C0000] <1> mov al, [u.uno] 27132 000056E6 D0E0 <1> shl al, 1 27133 000056E8 663BB0[82680000] <1> cmp si, [eax+p.ppid-2] 27134 000056EF 744D <1> je short ottys_3 ; * 27135 <1> ; 23/02/2022 27136 <1> ; check console tty of the process 27137 <1> ; (open permission must be given if the -requested- tty is 27138 <1> ; console tty of current process) 27139 000056F1 D0E8 <1> shr al, 1 27140 000056F3 38B0[A3680000] <1> cmp [eax+p.ttyc-1], dh ; console tty ? 27141 000056F9 7443 <1> je short ottys_3 27142 <1> ; 27143 <1> ; the tty is locked by another process 27144 <1> ; except the parent process (p.ppid) 27145 <1> ; 09/02/2022 27146 <1> ;mov dword [u.error], ERR_DEV_ACCESS 27147 <1> ; ; permission denied ! error 27148 <1> otty_err: ; 13/01/2014 27149 <1> ;or dl, dl ; DL = 0 -> called by sysstty 27150 <1> ;;jnz error 27151 <1> ; 05/12/2021 27152 <1> ;jz short otty_stc_retn 27153 <1> ;jmp error 27154 <1> ; 09/02/2022 27155 000056FB 80FA01 <1> cmp dl, 1 ; dl = 0 ? 27156 000056FE 7257 <1> jb short otty_retn ; yes, cf=1, called by sysstty 27157 <1> ; iopen (dl=1 or dl=2) 27158 00005700 C705[186D0000]0B00- <1> mov dword [u.error], ERR_DEV_ACCESS 27159 00005708 0000 <1> 27160 <1> ; permission denied ! error 27161 0000570A E956DAFFFF <1> jmp error 27162 <1> ;otty_stc_retn: 27163 <1> ;stc 27164 <1> ;retn 27165 <1> ottys_0: 27166 <1> ; 05/12/2021 27167 <1> otty_ret: 27168 <1> ; 13/01/2014 27169 0000570F 80FE07 <1> cmp dh, 7 27170 00005712 7624 <1> jna short ottys_2 27171 <1> ; 16/11/2015 27172 <1> com_port_check: 27173 00005714 BE[D2670000] <1> mov esi, com1p 27174 00005719 80FE08 <1> cmp dh, 8 ; COM1 (tty8) ? 27175 0000571C 7601 <1> jna short ottys_1 ; yes, it is COM1 27176 0000571E 46 <1> inc esi ; no, it is COM2 (tty9) 27177 <1> ottys_1: 27178 <1> ; 12/11/2015 27179 0000571F 803E00 <1> cmp byte [esi], 0 ; E3h (or 23h) 27180 00005722 7714 <1> ja short com_port_ready 27181 <1> ; 27182 <1> ; 09/02/2022 27183 00005724 80FA01 <1> cmp dl, 1 ; dl = 0 ? 27184 00005727 722E <1> jb short otty_retn ; yes, cf=1, called by sysstty 27185 00005729 C705[186D0000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY 27186 00005731 0000 <1> 27187 <1> ; device not ready ! error 27188 <1> ;jmp short otty_err 27189 00005733 E92DDAFFFF <1> jmp error 27190 <1> com_port_ready: 27191 <1> ottys_2: 27192 <1> ; 03/03/2022 27193 <1> ;or cl, cl ; cl = lock/owner, ch = open count 27194 <1> ;jnz short ottys_3 27195 00005738 8A0D[F56C0000] <1> mov cl, [u.uno] 27196 <1> ottys_3: 27197 0000573E FEC5 <1> inc ch 27198 00005740 66890B <1> mov [ebx], cx ; set tty lock again 27199 <1> ; 06/12/2013 27200 00005743 FEC6 <1> inc dh ; tty number + 1 27201 00005745 BB[DA6C0000] <1> mov ebx, u.ttyp 27202 <1> ; 13/01/2014 27203 <1> ;test dl, 2 ; open for read sign 27204 <1> ;jnz short ottys_4 27205 <1> ; 05/12/2021 27206 <1> ;test dl, 2 27207 <1> ;jz short ottys_4 ; open for read 27208 <1> ; 01/01/2022 27209 0000574A F6C201 <1> test dl, 1 27210 0000574D 7501 <1> jnz short ottys_4 ; open for read (dl=1) 27211 <1> ; dl=2 (open for write) or dl=0 (sysstty) 27212 0000574F 43 <1> inc ebx 27213 <1> ottys_4: 27214 <1> ; Set 'u.ttyp' ('the recent TTY') value 27215 00005750 8833 <1> mov [ebx], dh ; tty number + 1 27216 <1> ; 09/02/2022 27217 00005752 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 27218 00005754 7401 <1> jz short otty_retn ; 03/03/2022 27219 <1> sret: 27220 <1> ;pop ax 27221 <1> ; 05/12/2021 27222 00005756 58 <1> pop eax 27223 <1> otty_retn: ; 09/02/2022 27224 <1> iclose_retn: 27225 00005757 C3 <1> retn 27226 <1> 27227 <1> ; 27228 <1> ; Original UNIX v1 'otty' routine: 27229 <1> ; 27230 <1> ;mov $100,*$tks / set interrupt enable bit (zero others) in 27231 <1> ; / reader status reg 27232 <1> ;mov $100,*$tps / set interrupt enable bit (zero others) in 27233 <1> ; / punch status reg 27234 <1> ;mov tty+[ntty*8]-8+6,r5 / r5 points to the header of the 27235 <1> ; / console tty buffer 27236 <1> ;incb (r5) / increment the count of processes that opened the 27237 <1> ; / console tty 27238 <1> ;tst u.ttyp / is there a process control tty (i.e., has a tty 27239 <1> ; / buffer header 27240 <1> ;bne sret / address been loaded into u.ttyp yet)? yes, branch 27241 <1> ;mov r5,u.ttyp / no, make the console tty the process control 27242 <1> ; / tty 27243 <1> ;br sret / ? 27244 <1> ;sret: 27245 <1> ;clr *$ps / set processor priority to zero 27246 <1> ; pop ax 27247 <1> ;mov (sp)+,r1 / pop stack to r1 27248 <1> ;3: 27249 <1> ; retn 27250 <1> ;rts r0 27251 <1> 27252 <1> ;ocvt: ; < open tty > 27253 <1> ; 13/01/2014 27254 <1> ; 06/12/2013 (major modification: p.ttyc, u.ttyp) 27255 <1> ; 24/09/2013 consistency check -> ok 27256 <1> ; 16/09/2013 27257 <1> ; 03/09/2013 27258 <1> ; 27/08/2013 27259 <1> ; 16/08/2013 27260 <1> ; 16/07/2013 27261 <1> ; 27/05/2013 27262 <1> ; 21/05/2013 27263 <1> ; 27264 <1> ; Retro UNIX 8086 v1 modification ! 27265 <1> ; 27266 <1> ; In original UNIX v1, 'ocvt' routine 27267 <1> ; (exactly different than this one) 27268 <1> ; was in 'u9.s' file. 27269 <1> ; 27270 <1> ; 16/07/2013 27271 <1> ; Retro UNIX 8086 v1 modification: 27272 <1> ; If a tty is open for read or write by 27273 <1> ; a process (u.uno), only same process can open 27274 <1> ; same tty to write or read (R->R&W or W->W&R). 27275 <1> ; 27276 <1> ; INPUT: DL=2 for Read DL=1 for Write 27277 <1> 27278 <1> ; 16/09/2013 27279 <1> ; sub al, 10 27280 <1> 27281 <1> ; 06/12/2013 27282 <1> ;cmp al, 7 27283 <1> ;jna short ottyp 27284 <1> ; 13/01/2014 27285 <1> ;jmp short ottyp 27286 <1> 27287 <1> ;oppt: / open paper tape for reading or writing 27288 <1> ; mov $100,*$prs / set reader interrupt enable bit 27289 <1> ; tstb pptiflg / is file already open 27290 <1> ; bne 2f / yes, branch 27291 <1> ;1: 27292 <1> ; mov $240,*$ps / no, set processor priority to 5 27293 <1> ; jsr r0,getc; 2 / remove all entries in clist 27294 <1> ; br .+4 / for paper tape input and place in free list 27295 <1> ; br 1b 27296 <1> ; movb $2,pptiflg / set pptiflg to indicate file just open 27297 <1> ; movb $10.,toutt+1 / place 10 in paper tape input tout entry 27298 <1> ; br sret 27299 <1> ;2: 27300 <1> ; jmp error / file already open 27301 <1> 27302 <1> ; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification 27303 <1> iclose: 27304 <1> ; 09/02/2022 27305 <1> ; 05/12/2021 - Retro UNIX 386 v1.2 27306 <1> ; 10/04/2021 27307 <1> ; 08/04/2021 27308 <1> ; 04/04/2021 - Retro UNIX 386 v2 27309 <1> ; 19/05/2015 27310 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 27311 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 27312 <1> ; 27313 <1> ; close file whose i-number is in r1 27314 <1> ; 27315 <1> ; INPUTS -> 27316 <1> ; r1 - inode number 27317 <1> ; OUTPUTS -> 27318 <1> ; file's inode in core 27319 <1> ; r1 - inode number (positive) 27320 <1> ; 27321 <1> ; ((AX = R1)) 27322 <1> ; ((Modified registers: -ebx-, edx)) 27323 <1> ; 27324 <1> ;;/ close file whose i-number is in r1 27325 <1> ; mov dl, 2 ; 12/01/2014 27326 <1> ; test ah, 80h ; Bit 15 of AX 27327 <1> ; ;tst r1 / test i-number 27328 <1> ; ;jnz short iclose_2 27329 <1> ; ;blt 2f / if neg., branch 27330 <1> ; jz short iclose_0 ; 30/07/2013 27331 <1> ; ; 16/07/2013 27332 <1> ; neg ax ; make it positive 27333 <1> ; ; 12/01/2014 27334 <1> ; dec dl ; dl = 1 (open for write) 27335 <1> ;iclose_0: 27336 <1> ; cmp ax, 40 27337 <1> ; ;cmp r1,$40. / is it a special file 27338 <1> ; ja short iclose_retn ; 13/01/2014 27339 <1> ; ;bgt 3b / no, return 27340 <1> ; ; 12/01/2014 27341 <1> ; ; DL=2 -> special file was opened for reading 27342 <1> ; ; DL=1 -> special file was opened for writing 27343 <1> 27344 <1> ; 04/04/2021 27345 <1> ; INPUT: 27346 <1> ; (e)ax = inode number 27347 <1> ; dl = open mode 27348 <1> ; 0 = control mode 27349 <1> ; 1 = read 27350 <1> ; 2 = write 27351 <1> ; OUTPUT: 27352 <1> ; none 27353 <1> ; (if cf=1 -> eax = error code) 27354 <1> ; (if cf=0 -> ax = inode number) 27355 <1> 27356 <1> ; 10/04/2021 27357 <1> ; Modified registers: ebx, ecx, edx, esi, edi, (ebp) 27358 <1> 27359 <1> ; 05/12/2021 27360 <1> ; 08/04/2021 27361 <1> 27362 00005758 52 <1> push edx 27363 00005759 E817F4FFFF <1> call iget 27364 0000575E 5A <1> pop edx 27365 <1> 27366 0000575F 8A0D[25680000] <1> mov cl, [i.flgs+1] 27367 <1> 27368 <1> ; if i.flgs bit 15 is 1, it is regular file 27369 <1> ;test byte [i.flgs+1], 80h ; is it a special file? 27370 00005765 F6C180 <1> test cl, 80h ; is it a special file? 27371 00005768 75ED <1> jnz short iclose_retn ; no 27372 <1> 27373 <1> ;; inode flags - bit 13 must be 1 27374 <1> ;test cl, 20h ; is it a valid device inode 27375 <1> ;jz short iclose_retn ; no ; 19/01/2022 27376 <1> 27377 <1> ;push ax 27378 <1> ; ;mov r1,-(sp) / yes, save r1 on stack 27379 <1> ;movzx ebx, al 27380 <1> ;shl bx, 2 27381 <1> ; ; asl r1 27382 <1> ;add ebx, iclose_1 - 4 27383 <1> ;jmp dword [ebx] 27384 <1> ; ; jmp *1f-2(r1) / compute jump address and transfer 27385 <1> 27386 <1> ; 05/12/2021 27387 0000576A 50 <1> push eax ; save inode number 27388 <1> ; device file 27389 0000576B BB[85570000] <1> mov ebx, iclose_1 27390 00005770 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 27391 00005773 720E <1> jb short iclose_0 27392 00005775 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 27393 00005778 7709 <1> ja short iclose_0 27394 <1> ; convert v2 inode number to v1 device inode number 27395 0000577A 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 27396 0000577C 89C1 <1> mov ecx, eax 27397 0000577E C0E102 <1> shl cl, 2 ; * 4 27398 00005781 01CB <1> add ebx, ecx 27399 <1> iclose_0: 27400 00005783 FF23 <1> jmp dword [ebx] 27401 <1> ; jmp *1f-2(r1) 27402 <1> iclose_1: ; 1: 27403 00005785 [7E4F0000] <1> dd null ; 05/12/2021 27404 00005789 [D5570000] <1> dd ctty ; tty, AX = 1 (runix) 27405 0000578D [30580000] <1> dd cret ; mem, AX = 2 (runix) 27406 00005791 [30580000] <1> dd cret ; fd0, AX = 3 (runix only) 27407 00005795 [30580000] <1> dd cret ; fd1, AX = 4 (runix only) 27408 00005799 [30580000] <1> dd cret ; hd0, AX = 5 (runix only) 27409 0000579D [30580000] <1> dd cret ; hd1, AX = 6 (runix only) 27410 000057A1 [30580000] <1> dd cret ; hd2, AX = 7 (runix only) 27411 000057A5 [30580000] <1> dd cret ; hd3, AX = 8 (runix only) 27412 000057A9 [30580000] <1> dd cret ; lpr, AX = 9 (runix) 27413 <1> ;dd error; lpr, AX = 9 (error!) 27414 <1> ;;dd ejec ;;lpr, AX = 9 27415 000057AD [E4570000] <1> dd ccvt ; tty0, AX = 10 (runix) 27416 000057B1 [E4570000] <1> dd ccvt ; tty1, AX = 11 (runix) 27417 000057B5 [E4570000] <1> dd ccvt ; tty2, AX = 12 (runix) 27418 000057B9 [E4570000] <1> dd ccvt ; tty3, AX = 13 (runix) 27419 000057BD [E4570000] <1> dd ccvt ; tty4, AX = 14 (runix) 27420 000057C1 [E4570000] <1> dd ccvt ; tty5, AX = 15 (runix) 27421 000057C5 [E4570000] <1> dd ccvt ; tty6, AX = 16 (runix) 27422 000057C9 [E4570000] <1> dd ccvt ; tty7, AX = 17 (runix) 27423 000057CD [E4570000] <1> dd ccvt ; COM1, AX = 18 (runix only) 27424 000057D1 [E4570000] <1> dd ccvt ; COM2, AX = 19 (runix only) 27425 <1> 27426 <1> ; 1: 27427 <1> ; ctty / tty 27428 <1> ; cppt / ppt 27429 <1> ; sret / mem 27430 <1> ; sret / rf0 27431 <1> ; sret / rk0 27432 <1> ; sret / tap0 27433 <1> ; sret / tap1 27434 <1> ; sret / tap2 27435 <1> ; sret / tap3 27436 <1> ; sret / tap4 27437 <1> ; sret / tap5 27438 <1> ; sret / tap6 27439 <1> ; sret / tap7 27440 <1> ; ccvt / tty0 27441 <1> ; ccvt / tty1 27442 <1> ; ccvt / tty2 27443 <1> ; ccvt / tty3 27444 <1> ; ccvt / tty4 27445 <1> ; ccvt / tty5 27446 <1> ; ccvt / tty6 27447 <1> ; ccvt / tty7 27448 <1> ; error / crd 27449 <1> 27450 <1> ;iclose_2: ; 2: / negative i-number 27451 <1> ;neg ax 27452 <1> ;neg r1 / make it positive 27453 <1> ;cmp ax, 40 27454 <1> ;cmp r1,$40. / is it a special file? 27455 <1> ;ja short @b 27456 <1> ;bgt 3b / no. return 27457 <1> ;push ax 27458 <1> ;mov r1,-(sp) 27459 <1> ;movzx ebx, al 27460 <1> ;shl bx, 1 27461 <1> ;asl r1 / yes. compute jump address and transfer 27462 <1> ;add ebx, iclose_3 - 2 27463 <1> ;jmp dword [ebx] 27464 <1> ;jmp *1f-2(r1) / figure out 27465 <1> ;iclose_3: 27466 <1> ;dd ctty ; tty, AX = 1 (runix) 27467 <1> ;dd sret ; mem, AX = 2 (runix) 27468 <1> ;dd sret ; fd0, AX = 3 (runix only) 27469 <1> ;dd sret ; fd1, AX = 4 (runix only) 27470 <1> ;dd sret ; hd0, AX = 5 (runix only) 27471 <1> ;dd sret ; hd1, AX = 6 (runix only) 27472 <1> ;dd sret ; hd2, AX = 7 (runix only) 27473 <1> ;dd sret ; hd3, AX = 8 (runix only) 27474 <1> ;;dd sret ; lpr, AX = 9 27475 <1> ;dd ejec ; lpr, AX = 9 (runix) 27476 <1> ;dd ccvt ; tty0, AX = 10 (runix) 27477 <1> ;dd ccvt ; tty1, AX = 11 (runix) 27478 <1> ;dd ccvt ; tty2, AX = 12 (runix) 27479 <1> ;dd ccvt ; tty3, AX = 13 (runix) 27480 <1> ;dd ccvt ; tty4, AX = 14 (runix) 27481 <1> ;dd ccvt ; tty5, AX = 15 (runix) 27482 <1> ;dd ccvt ; tty6, AX = 16 (runix) 27483 <1> ;dd ccvt ; tty7, AX = 17 (runix) 27484 <1> ;dd ccvt ; COM1, AX = 18 (runix only) 27485 <1> ;dd ccvt ; COM2, AX = 19 (runix only) 27486 <1> 27487 <1> ;1: 27488 <1> ; ctty / tty 27489 <1> ; leadr / ppt 27490 <1> ; sret / mem 27491 <1> ; sret / rf0 27492 <1> ; sret / rk0 27493 <1> ; sret / tap0 27494 <1> ; sret / tap1 27495 <1> ; sret / tap2 27496 <1> ; sret / tap3 27497 <1> ; sret / tap4 27498 <1> ; sret / tap5 27499 <1> ; sret / tap6 27500 <1> ; sret / tap7 27501 <1> ; ccvt / tty0 27502 <1> ; ccvt / tty1 27503 <1> ; ccvt / tty2 27504 <1> ; ccvt / tty3 27505 <1> ; ccvt / tty4 27506 <1> ; ccvt / tty5 27507 <1> ; ccvt / tty6 27508 <1> ; ccvt / tty7 27509 <1> ;/ ejec / lpr 27510 <1> 27511 <1> ctty: ; / close console tty 27512 <1> ; 09/02/2022 27513 <1> ; 06/02/2022 27514 <1> ; 08/01/2022 27515 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 27516 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 27517 <1> ; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1) 27518 <1> ; 27519 <1> ; Retro UNIX 8086 v1 modification ! 27520 <1> ; (DL = 2 -> it is open for reading) 27521 <1> ; (DL = 1 -> it is open for writing) 27522 <1> ; (DL = 0 -> it is open for sysstty system call) 27523 <1> ; 27524 <1> ; 06/12/2013 27525 000057D5 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 27526 000057DC 8A83[A3680000] <1> mov al, [ebx+p.ttyc-1] 27527 <1> ; 13/01/2014 27528 <1> ;jmp short cttyp 27529 <1> ; 06/02/2022 27530 000057E2 EB04 <1> jmp short ctty_0 27531 <1> ccvt: 27532 000057E4 2C0A <1> sub al, 10 27533 <1> cttyp: 27534 <1> ; 08/01/2022 27535 000057E6 31DB <1> xor ebx, ebx 27536 <1> ctty_0: ; 06/02/2022 27537 <1> ; 09/02/2022 27538 <1> ; DL=2 -> open for writing 27539 <1> ; DL=1 -> open for reading 27540 <1> ; DL=0 -> open for sysstty system call 27541 <1> ; 08/01/2022 27542 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 27543 <1> ; 18/05/2015 (32 bit modifications) 27544 <1> ; 16/08/2013 - 26/01/2014 27545 <1> ;movzx ebx, al ; tty number (0 to 9) 27546 <1> ; 08/01/2022 27547 000057E8 88C3 <1> mov bl, al 27548 000057EA D0E3 <1> shl bl, 1 ; aligned to word 27549 <1> ; 26/01/2014 27550 000057EC 81C3[B4670000] <1> add ebx, ttyl 27551 000057F2 88C6 <1> mov dh, al ; tty number 27552 000057F4 668B03 <1> mov ax, [ebx] 27553 <1> ; AL = lock value (0 or process number) 27554 <1> ; AH = open count 27555 000057F7 20E4 <1> and ah, ah 27556 000057F9 7514 <1> jnz short ctty_ret 27557 <1> ; 09/02/2022 27558 000057FB 80FA01 <1> cmp dl, 1 ; DL = 0 -> called by sysstty 27559 000057FE 7231 <1> jb short ctty_stc_retn ; cf=1 27560 <1> ; iclose (dl=1 or dl=2) 27561 00005800 C705[186D0000]0A00- <1> mov dword [u.error], ERR_DEV_NOT_OPEN 27562 00005808 0000 <1> 27563 <1> ; device not open ! error 27564 <1> ;jmp short ctty_err ; open count = 0, it is not open ! 27565 0000580A E956D9FFFF <1> jmp error 27566 <1> ; 26/01/2014 27567 <1> ctty_ret: 27568 0000580F FECC <1> dec ah ; decrease open count 27569 00005811 7502 <1> jnz short ctty_1 27570 00005813 30C0 <1> xor al, al ; unlock/free tty 27571 <1> ctty_1: 27572 00005815 668903 <1> mov [ebx], ax ; close tty instance 27573 <1> ; 27574 00005818 BB[DA6C0000] <1> mov ebx, u.ttyp 27575 <1> ;;test dl, 1 ; open for write sign 27576 <1> ;;jz short ctty_2 27577 <1> ; 05/12/2021 27578 <1> ;test dl, 2 ; open for write sign 27579 <1> ;jz short ctty_2 27580 <1> ; 09/02/2022 27581 0000581D F6C201 <1> test dl, 1 ; open for read sign 27582 00005820 7501 <1> jnz short ctty_2 27583 <1> ; open for write (dl=0 or dl=2) 27584 00005822 43 <1> inc ebx 27585 <1> ctty_2: 27586 00005823 FEC6 <1> inc dh ; tty number + 1 27587 00005825 3A33 <1> cmp dh, [ebx] 27588 <1> ;jne short cret 27589 00005827 7503 <1> jne short ctty_3 ; 09/02/2022 27590 <1> ; Reset/Clear 'u.ttyp' ('the recent TTY') value 27591 00005829 C60300 <1> mov byte [ebx], 0 27592 <1> ctty_3: 27593 <1> ; 09/02/2022 27594 0000582C 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 27595 0000582E 7401 <1> jz short ctty_4 27596 <1> cret: 27597 <1> ;pop ax 27598 <1> ; 05/12/2021 27599 00005830 58 <1> pop eax 27600 <1> ctty_stc_retn: ; 09/02/2022 27601 <1> ctty_4: 27602 00005831 C3 <1> retn 27603 <1> 27604 <1> ;ctty_err: ; 13/01/2014 27605 <1> ; or dl, dl ; DL = 0 -> called by sysstty 27606 <1> ; jnz error 27607 <1> ; stc 27608 <1> ; retn 27609 <1> 27610 <1> ; Original UNIX v1 'ctty' routine: 27611 <1> ; 27612 <1> ;mov tty+[ntty*8]-8+6,r5 27613 <1> ; ;/ point r5 to the console tty buffer 27614 <1> ;decb (r5) / dec number of processes using console tty 27615 <1> ;br sret / return via sret 27616 <1> 27617 <1> ;ccvt: ; < close tty > 27618 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 27619 <1> ; 27620 <1> ; Retro UNIX 8086 v1 modification ! 27621 <1> ; 27622 <1> ; In original UNIX v1, 'ccvt' routine 27623 <1> ; (exactly different than this one) 27624 <1> ; was in 'u9.s' file. 27625 <1> ; 27626 <1> ; DL = 2 -> it is open for reading 27627 <1> ; DL = 1 -> it is open for writing 27628 <1> ; 27629 <1> ; 17/09/2013 27630 <1> ;sub al, 10 27631 <1> ;cmp al, 7 27632 <1> ;jna short cttyp 27633 <1> ; 13/01/2014 27634 <1> ;jmp short cttyp 27635 <1> 27636 <1> ;cppt: / close paper tape 27637 <1> ; clrb pptiflg / set pptiflg to indicate file not open 27638 <1> ;1: 27639 <1> ; mov $240,*$ps /set process or priority to 5 27640 <1> ; jsr r0,getc; 2 / remove all ppt input entries from clist 27641 <1> ; / and assign to free list 27642 <1> ; br sret 27643 <1> ; br 1b 27644 <1> 27645 <1> ;ejec: 27646 <1> ; jmp error 27647 <1> ;/ejec: 27648 <1> ;/ mov $100,*$lps / set line printer interrupt enable bit 27649 <1> ;/ mov $14,r1 / 'form feed' character in r1 (new page). 27650 <1> ;/ jsr r0,lptoc / space the printer to a new page 27651 <1> ;/ br sret / return to caller via 'sret' 27652 <1> 27653 <1> ejec: 27654 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 - Printer Initialization 27655 <1> lpt_init: 27656 <1> ; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 27657 <1> ; 27658 <1> ; Default printer port: 378h ; LPT1 27659 <1> 27660 00005832 B401 <1> mov ah, 1 ; INITIALIZE THE PRINTER PORT 27661 <1> ;call int17h 27662 00005834 E846FAFFFF <1> call PRNOP 27663 00005839 7414 <1> jz short lpt_init_ok 27664 <1> 27665 <1> ; replace error code with 'device not ready' error 27666 <1> ; (this may be better for 'sysopen') 27667 0000583B B80F000000 <1> mov eax, ERR_PRN_NOT_RDY 27668 00005840 A3[186D0000] <1> mov [u.error], eax 27669 <1> ;jmp sysret ; (may be) ? ([u.r0] = file descriptor) 27670 00005845 A3[A46C0000] <1> mov [u.r0], eax 27671 0000584A E916D9FFFF <1> jmp error ; (better) 27672 <1> 27673 <1> lpt_init_ok: 27674 <1> ;jmp short cret 27675 0000584F 58 <1> pop eax ; inode number 27676 00005850 C3 <1> retn 27677 <1> 27678 %include 'u8.s' ; 11/06/2015 27679 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 27680 <1> ; (re-write kernel for test by using previous version without a major defect) 27681 <1> ; **************************************************************************** 27682 <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - SYS8.INC 27683 <1> ; Last Modification: 19/07/2022 27684 <1> ; ---------------------------------------------------------------------------- 27685 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 27686 <1> ; (v0.1 - Beginning: 11/07/2012) 27687 <1> ; 27688 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 27689 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 27690 <1> ; 27691 <1> ; 27692 <1> ; 27693 <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s 27694 <1> ; 27695 <1> ; **************************************************************************** 27696 <1> 27697 <1> ; 15/07/2022 - Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 27698 <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 27699 <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 27700 <1> ;--------------------------------------------------------------------- 27701 <1> ; Buffer Header: -8 bytes- 27702 <1> ; word 1 - byte 0 - device (disk index) number (0 to 5) 27703 <1> ; byte 1 - status bits 27704 <1> ; bit 0 - valid buffer bit (1 = valid, 0 = invalid, new) 27705 <1> ; bit 1 - write bit (also modified bit) 27706 <1> ; bit 2 - read bit 27707 <1> ; bit 3 to bit 7 are not used 27708 <1> ; word 2 - byte & byte 3 not used 27709 <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7: 27710 <1> ; physical block/sector address (32 bit LBA) 27711 <1> ;--------------------------------------------------------------------- 27712 <1> 27713 <1> ;; I/O Buffer - Retro UNIX 386 v1 modification 27714 <1> ;; (8+512 bytes, 8 bytes header, 512 bytes data) 27715 <1> ;; Word 1, byte 0 = device id 27716 <1> ;; Word 1, byte 1 = status bits (bits 8 to 15) 27717 <1> ;; bit 9 = write bit 27718 <1> ;; bit 10 = read bit 27719 <1> ;; bit 12 = waiting to write bit 27720 <1> ;; bit 13 = waiting to read bit 27721 <1> ;; bit 15 = inhibit bit 27722 <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015) 27723 <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 27724 <1> ;; (In fact, it is 32 bit LBA for Retro UNIX 386 v1) 27725 <1> ;; 27726 <1> ;; I/O Buffer ((8+512 bytes in original Unix v1)) 27727 <1> ;; ((4+512 bytes in Retro UNIX 8086 v1)) 27728 <1> ;; 27729 <1> ;; I/O Queue Entry (of original UNIX operating system v1) 27730 <1> ;; Word 1, Byte 0 = device id 27731 <1> ;; Word 1, Byte 1 = (bits 8 to 15) 27732 <1> ;; bit 9 = write bit 27733 <1> ;; bit 10 = read bit 27734 <1> ;; bit 12 = waiting to write bit 27735 <1> ;; bit 13 = waiting to read bit 27736 <1> ;; bit 15 = inhibit bit 27737 <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1) 27738 <1> ;; 27739 <1> ;; Original UNIX v1 -> 27740 <1> ;; Word 3 = number of words in buffer (=256) 27741 <1> ;; Original UNIX v1 -> 27742 <1> ;; Word 4 = bus address (addr of first word of data buffer) 27743 <1> ;; 27744 <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes ! 27745 <1> ;; 27746 <1> ;; Device IDs (of Retro Unix 8086 v1) 27747 <1> ;; 0 = fd0 27748 <1> ;; 1 = fd1 27749 <1> ;; 2 = hd0 27750 <1> ;; 3 = hd1 27751 <1> ;; 4 = hd2 27752 <1> ;; 5 = hd3 27753 <1> 27754 <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015 27755 <1> 27756 <1> ; 08/02/2022 27757 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 27758 <1> rfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 27759 <1> ; 26/04/2013 27760 <1> ; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 27761 <1> ;sub ax, 3 ; zero based device number (Floppy disk) 27762 <1> ;jmp short bread ; **** returns to routine that called readi 27763 <1> 27764 <1> ; 08/02/2022 27765 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 27766 <1> rhd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 27767 <1> ; 26/04/2013 27768 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 27769 <1> ;sub ax, 3 ; zero based device number (Hard disk) 27770 <1> ;jmp short bread ; **** returns to routine that called readi 27771 <1> 27772 <1> bread: 27773 <1> ; 19/07/2022 27774 <1> ; 15/07/2022 27775 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 27776 <1> ; 08/02/2022 27777 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 27778 <1> ; 14/07/2015 27779 <1> ; 10/07/2015 27780 <1> ; 09/06/2015 27781 <1> ; 07/06/2015 (Retro UNIX 386 v1 - Beginning) 27782 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 27783 <1> ; 27784 <1> ; / read a block from a block structured device 27785 <1> ; 27786 <1> ; INPUTS -> 27787 <1> ; [u.fopf] points to the block number 27788 <1> ; ECX = maximum block number allowed on device 27789 <1> ; ; that was an arg to bread, in original Unix v1, but 27790 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 27791 <1> ; [u.count] number of bytes to read in 27792 <1> ; OUTPUTS -> 27793 <1> ; [u.base] starting address of data block or blocks in user area 27794 <1> ; [u.fopf] points to next consecutive block to be read 27795 <1> ; 27796 <1> ; ((Modified registers: eax, edx, ecx, ebx, esi, edi)) 27797 <1> ; 27798 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if read 27799 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 27800 <1> ; is increased by 1. For example: If user/program request 27801 <1> ; to read 16 bytes in current block, 'sys read' increases 27802 <1> ; the next block number just as 512 byte reading is done. 27803 <1> ; This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 27804 <1> ; for user (u) structure compatibility (because 16 bit is not 27805 <1> ; enough to keep byte position/offset of the disk), this 27806 <1> ; defect will not be corrected, user/program must request 27807 <1> ; 512 byte read per every 'sys read' call to block devices 27808 <1> ; for achieving correct result. In future version(s), 27809 <1> ; this defect will be corrected by using different 27810 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 27811 <1> 27812 <1> ; jsr r0,tstdeve / error on special file I/O 27813 <1> ; / (only works on tape) 27814 <1> ; mov *u.fofp,r1 / move block number to r1 27815 <1> ; mov $2.-cold,-(sp) / "2-cold" to stack 27816 <1> ;1: 27817 <1> ; cmp r1,(r0) / is this block # greater than or equal to 27818 <1> ; / maximum block # allowed on device 27819 <1> ; jnb short @f 27820 <1> ; bhis 1f / yes, 1f (error) 27821 <1> ; mov r1,-(sp) / no, put block # on stack 27822 <1> ; jsr r0,preread / read in the block into an I/O buffer 27823 <1> ; mov (sp)+,r1 / return block # to r1 27824 <1> ; inc r1 / bump block # to next consecutive block 27825 <1> ; dec (sp) / "2-1-cold" on stack 27826 <1> ; bgt 1b / 2-1-cold = 0? No, go back and read in next block 27827 <1> ;1: 27828 <1> ; tst (sp)+ / yes, pop stack to clear off cold calculation 27829 <1> ;push ecx ; ** 27830 <1> ; 26/04/2013 27831 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 27832 00005851 2C03 <1> sub al, 3 27833 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 27834 00005853 A2[176D0000] <1> mov [u.brwdev], al 27835 <1> ; 09/06/2015 27836 <1> ;movzx ebx, al 27837 <1> ;mov ecx, [ebx+drv.size] ; disk size (in sectors) 27838 <1> ; 12/01/2022 (BugFix) 27839 00005858 C0E002 <1> shl al, 2 ; * 4 27840 0000585B 8B88[92620000] <1> mov ecx, [eax+drv.size] ; disk size (in sectors) 27841 <1> bread_0: 27842 00005861 51 <1> push ecx ; ** ; 09/06/2015 27843 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 27844 <1> ; [u.fopf] points to byte position in disk, not sector/block ! 27845 00005862 8B1D[B86C0000] <1> mov ebx, [u.fofp] 27846 00005868 8B03 <1> mov eax, [ebx] 27847 0000586A C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 27848 <1> ; mov *u.fofp,r1 / restore r1 to initial value of the 27849 <1> ; / block # 27850 0000586D 39C8 <1> cmp eax, ecx 27851 <1> ; cmp r1,(r0)+ / block # greater than or equal to maximum 27852 <1> ; / block number allowed 27853 <1> ;jnb error ; 18/04/2013 27854 <1> ; bhis error10 / yes, error 27855 <1> ; 08/02/2022 27856 <1> ;jb short bread_1 27857 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 27858 <1> ;jmp error 27859 0000586F 7346 <1> jnb short brw_oov_err ; 'out of volume' error 27860 <1> bread_1: 27861 <1> ;inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 27862 <1> ; inc *u.fofp / no, *u.fofp has next block number 27863 <1> ; EAX = Block number (zero based) 27864 <1> ;;jsr r0,preread / read in the block whose number is in r1 27865 <1> preread: ;; call preread 27866 00005871 BF[176D0000] <1> mov edi, u.brwdev ; block device number for direct I/O 27867 00005876 E8E1010000 <1> call bufaloc_0 ; 26/04/2013 27868 <1> ;; jc error 27869 <1> ; EBX = Buffer (Header) Address -Physical- 27870 <1> ; EAX = Block/Sector number (r1) 27871 <1> ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number) 27872 <1> ; 14/03/2013 27873 0000587B 7411 <1> jz short bread_2 ; Retro UNIX 8086 v1 modification 27874 <1> ; br 1f / branch if block already in a I/O buffer 27875 0000587D 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 27876 <1> ; bis $2000,(r5) / set read bit (bit 10 in I/O buffer) 27877 00005882 E8AD010000 <1> call poke 27878 <1> ; jsr r0,poke / perform the read 27879 <1> ;;jc error ;2 0/07/2013 27880 <1> ; 1: 27881 <1> ; clr *$ps / ps = 0 27882 <1> ; rts r0 27883 <1> ; 08/02/2022 27884 00005887 7305 <1> jnc short bread_2 27885 00005889 E919010000 <1> jmp dskrd_err 27886 <1> ; 27887 <1> ;; return from preread 27888 <1> bread_2: 27889 <1> ; 15/07/2022 27890 <1> ;or word [ebx], 4000h 27891 <1> ; ; bis $40000,(r5) 27892 <1> ; ; / set bit 14 of the 1st word of the I/O buffer 27893 <1> bread_3: ; 1: 27894 <1> ; 15/07/2022 27895 <1> ;test word [ebx], 2400h 27896 <1> ; ; bit $22000,(r5) / are 10th and 13th bits set (read bits) 27897 <1> ;jz short bread_4 27898 <1> ; ; beq 1f / no 27899 <1> ; ; cmp cdev,$1 / disk or drum? 27900 <1> ; ; ble 2f / yes 27901 <1> ; ; tstb uquant / is the time quantum = 0? 27902 <1> ; ; bne 2f / no, 2f 27903 <1> ; ; mov r5,-(sp) / yes, save r5 (buffer address) 27904 <1> ; ; jsr r0,sleep; 31. 27905 <1> ; ; / put process to sleep in channel 31 (tape) 27906 <1> ; ; mov (sp)+,r5 / restore r5 27907 <1> ; ; br 1b / go back 27908 <1> ; 2: / drum or disk 27909 <1> ;; mov cx, [s.wait_]+2 ;; 29/07/2013 27910 <1> ;call idle 27911 <1> ; ; jsr r0,idle; s.wait+2 / wait 27912 <1> ;jmp short bread_3 27913 <1> ; ; br 1b 27914 <1> bread_4: ; 1: / 10th and 13th bits not set 27915 <1> ;and word [ebx], 0BFFFh ; 1011111111111111b 27916 <1> ; ; bic $40000,(r5) / clear bit 14 27917 <1> ; ; jsr r0,tstdeve / test device for error (tape) 27918 <1> ; 15/07/2022 27919 0000588E 83C308 <1> add ebx, 8 27920 <1> ; add $8,r5 / r5 points to data in I/O buffer 27921 <1> ; 09/06/2015 27922 00005891 66833D[106D0000]00 <1> cmp word [u.pcount], 0 27923 00005899 7705 <1> ja short bread_5 27924 0000589B E8FCF7FFFF <1> call trans_addr_w ; translate virtual address to physical (w) 27925 <1> bread_5: 27926 <1> ; EBX = system (I/O) buffer address 27927 000058A0 E87C000000 <1> call dioreg 27928 <1> ; jsr r0,dioreg / do bookkeeping on u.count etc. 27929 <1> 27930 <1> ; 19/07/2022 27931 <1> ; EDI = user data offset (previous value of [u.pbase]) 27932 <1> ; ESI = pointer to file offset 27933 <1> ; EAX = system (I/O) buffer offset (>= EBX) 27934 <1> ; ECX = byte count 27935 <1> ; EBX = system buffer (data) address 27936 <1> 27937 <1> ; 19/07/2022 27938 000058A5 010E <1> add [esi], ecx ; new file (disk) offset 27939 000058A7 89C6 <1> mov esi, eax 27940 <1> 27941 <1> ; esi = start address of the transfer (in the buffer) 27942 <1> ; edi = [u.pbase], destination address in user's memory space 27943 <1> ; ecx = transfer count (in bytes) 27944 <1> ; 27945 <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning 27946 <1> ; / of users data 27947 000058A9 F3A4 <1> rep movsb 27948 <1> ; movb (r5)+,(r2)+ / move data from the I/O buffer 27949 <1> ; dec r3 / to the user's area in core starting at u.base 27950 <1> ; bne 1b 27951 000058AB 59 <1> pop ecx ; ** 27952 000058AC 833D[CC6C0000]00 <1> cmp dword [u.count], 0 27953 <1> ; tst u.count / done 27954 000058B3 77AC <1> ja short bread_0 ; 09/06/2015 27955 <1> ; beq 1f / yes, return 27956 <1> ; tst -(r0) / no, point r0 to the argument again 27957 <1> ; br bread / read some more 27958 <1> ; 1: 27959 000058B5 58 <1> pop eax ; **** 27960 <1> ; mov (sp)+,r0 27961 000058B6 C3 <1> retn ; 09/06/2015 27962 <1> ;jmp ret_ 27963 <1> ;jmp ret / jump to routine that called readi 27964 <1> 27965 <1> ; 08/02/2022 27966 <1> brw_oov_err: 27967 000058B7 C705[186D0000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 27968 000058BF 0000 <1> 27969 000058C1 E99FD8FFFF <1> jmp error 27970 <1> 27971 <1> ; 08/02/2022 27972 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 27973 <1> wfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 27974 <1> ; 26/04/2013 27975 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 27976 <1> ;sub ax, 3 ; zero based device number (Hard disk) 27977 <1> ;jmp short bwrite ; **** returns to routine that called writei 27978 <1> 27979 <1> ; 08/02/2022 27980 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 27981 <1> whd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 27982 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 27983 <1> ;sub ax, 3 ; zero based device number (Hard disk) 27984 <1> ;jmp short bwrite ; **** returns to routine that called writei ('jmp ret') 27985 <1> 27986 <1> bwrite: 27987 <1> ; 19/07/2022 27988 <1> ; (file offset bugfix for 'dskwr' error return situation) 27989 <1> ; 15/07/2022 27990 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 27991 <1> ; 08/02/2022 27992 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 27993 <1> ; 14/07/2015 27994 <1> ; 10/07/2015 27995 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 27996 <1> ; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1) 27997 <1> ; 27998 <1> ;; / write on block structured device 27999 <1> ; 28000 <1> ; INPUTS -> 28001 <1> ; [u.fopf] points to the block number 28002 <1> ; ECX = maximum block number allowed on device 28003 <1> ; ; that was an arg to bwrite, in original Unix v1, but 28004 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 28005 <1> ; [u.count] number of bytes to user desires to write 28006 <1> ; OUTPUTS -> 28007 <1> ; [u.fopf] points to next consecutive block to be written into 28008 <1> ; 28009 <1> ; ((Modified registers: edx, ecx, ebx, esi, edi)) 28010 <1> ; 28011 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if write 28012 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 28013 <1> ; is increased by 1. For example: If user/program request 28014 <1> ; to write 16 bytes in current block, 'sys write' increases 28015 <1> ; the next block number just as 512 byte writing is done. 28016 <1> ; This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 28017 <1> ; for user (u) structure compatibility (because 16 bit is not 28018 <1> ; enough to keep byte position/offset of the disk), this 28019 <1> ; defect will not be corrected, user/program must request 28020 <1> ; 512 byte write per every 'sys write' call to block devices 28021 <1> ; for achieving correct result. In future version(s), 28022 <1> ; this defect will be corrected by using different 28023 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 28024 <1> 28025 <1> ; jsr r0,tstdeve / test the device for an error 28026 <1> ;push ecx ; ** 28027 <1> ;26/04/2013 28028 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 28029 000058C6 2C03 <1> sub al, 3 28030 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 28031 000058C8 A2[176D0000] <1> mov [u.brwdev], al 28032 <1> ; 09/06/2015 28033 <1> ;movzx ebx, al 28034 <1> ;mov ecx, [ebx+drv.size] ; disk size (in sectors) 28035 <1> ; 12/01/2022 (BugFix) 28036 000058CD C0E002 <1> shl al, 2 ; * 4 28037 000058D0 8B88[92620000] <1> mov ecx, [eax+drv.size] ; disk size (in sectors) 28038 <1> bwrite_0: 28039 000058D6 51 <1> push ecx ; ** ; 09/06/2015 28040 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 28041 <1> ; [u.fopf] points to byte position in disk, not sector/block ! 28042 000058D7 8B1D[B86C0000] <1> mov ebx, [u.fofp] 28043 000058DD 8B03 <1> mov eax, [ebx] 28044 000058DF C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 28045 <1> ; mov *u.fofp,r1 / put the block number in r1 28046 000058E2 39C8 <1> cmp eax, ecx 28047 <1> ; cmp r1,(r0)+ / does block number exceed maximum allowable # 28048 <1> ; / block number allowed 28049 <1> ;jnb error ; 18/04/2013 28050 <1> ; bhis error10 / yes, error 28051 <1> ; 08/02/2022 28052 <1> ;jb short bwrite_1 28053 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 28054 <1> ;jmp error 28055 000058E4 73D1 <1> jnb short brw_oov_err ; 'out of volume' error 28056 <1> bwrite_1: 28057 <1> ;inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 28058 <1> ; inc *u.fofp / no, increment block number 28059 <1> ; 09/06/2015 - 10/07/2015 28060 000058E6 66833D[106D0000]00 <1> cmp word [u.pcount], 0 28061 000058EE 7705 <1> ja short bwrite_2 28062 000058F0 E8A3F7FFFF <1> call trans_addr_r ; translate virtual address to physical (r) 28063 <1> bwrite_2: 28064 000058F5 BF[176D0000] <1> mov edi, u.brwdev ; block device number for direct I/O 28065 000058FA E8C9000000 <1> call bwslot ; 26/04/2013 (wslot -> bwslot) 28066 <1> ; jsr r0,wslot / get an I/O buffer to write into 28067 <1> ; add $8,r5 / r5 points to data in I/O buffer 28068 000058FF E81D000000 <1> call dioreg 28069 <1> ; jsr r0,dioreg / do the necessary bookkeeping 28070 <1> 28071 <1> ; 19/07/2022 28072 <1> ; EDI = user data offset (previous value of [u.pbase]) 28073 <1> ; ESI = pointer to file offset 28074 <1> ; EAX = system (I/O) buffer offset (>= EBX) 28075 <1> ; ECX = byte count 28076 <1> ; EBX = system buffer (data) address 28077 <1> 28078 <1> ; 19/07/2022 - Erdogan Tan 28079 <1> ; ((Against a possible disk write failure/error, 28080 <1> ; file offset must not be updated/increased before 'dskwr' 28081 <1> ; but it was updated in 'dioreg'. I have modified 'dioreg' 28082 <1> ; and 'bwrite' procedures for that.)) 28083 <1> 28084 <1> ; 19/07/2022 28085 00005904 56 <1> push esi ; (!) ; save file offset (pointer) 28086 00005905 51 <1> push ecx ; (!!) ; save byte count 28087 <1> ;mov esi, eax 28088 <1> 28089 <1> ; esi = destination address (in the buffer) 28090 <1> ; edi = [u.pbase], start address of transfer in user's memory space 28091 <1> ; ecx = transfer count (in bytes) 28092 <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area 28093 <1> ;xchg esi, edi ; 14/07/2015 28094 <1> 28095 <1> ; 19/07/2022 28096 00005906 89FE <1> mov esi, edi 28097 00005908 89C7 <1> mov edi, eax 28098 <1> 28099 0000590A F3A4 <1> rep movsb 28100 <1> ; movb (r2)+,(r5)+ / ; r3, has the byte count 28101 <1> ; dec r3 / area to the I/O buffer 28102 <1> ; bne 1b 28103 <1> 28104 0000590C E8F0000000 <1> call dskwr 28105 <1> ; jsr r0,dskwr / write it out on the device 28106 <1> 28107 <1> ; 19/07/2022 28108 <1> ; (there is not a disk write error, we can increase file offset) 28109 00005911 58 <1> pop eax ; (!!) ; byte count 28110 00005912 5F <1> pop edi ; (!) ; file offset (pointer) 28111 <1> ; 28112 00005913 0107 <1> add [edi], eax ; new file offset (old offset + byte count) 28113 <1> 28114 00005915 59 <1> pop ecx ; ** 28115 <1> 28116 00005916 833D[CC6C0000]00 <1> cmp dword [u.count], 0 28117 <1> ; tst u.count / done 28118 0000591D 77B7 <1> ja short bwrite_0 ; 09/06/2015 28119 <1> ; beq 1f / yes, 1f 28120 <1> ; tst -(r0) / no, point r0 to the argument of the call 28121 <1> ; br bwrite / go back and write next block 28122 <1> ; 1: 28123 0000591F 58 <1> pop eax ; **** 28124 <1> ; mov (sp)+,r0 28125 00005920 C3 <1> retn ; 09/06/2015 28126 <1> ;jmp ret_ 28127 <1> ; jmp ret / return to routine that called writei 28128 <1> ;error10: 28129 <1> ; jmp error ; / see 'error' routine 28130 <1> 28131 <1> dioreg: 28132 <1> ; 19/07/2022 28133 <1> ; (file offset bugfix for 'dskwr' error return situation) 28134 <1> ; 28135 <1> ; 08/02/2022 (Retro UNIX 386 v1.2) 28136 <1> ; 14/07/2015 28137 <1> ; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block) 28138 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 28139 <1> ; 14/03/2013 (Retro UNIX 8086 v1) 28140 <1> ; 28141 <1> ; bookkeeping on block transfers of data 28142 <1> ; 28143 <1> ; * returns value of u.pbase before it gets updated, in EDI 28144 <1> ; * returns byte count (to transfer) in ECX (<=512) 28145 <1> ; 10/07/2015 28146 <1> ; * returns byte offset from beginning of current sector buffer 28147 <1> ; (beginning of data) in ESI 28148 <1> 28149 <1> ; 19/07/2022 28150 <1> ; OUTPUTS: 28151 <1> ; EDI = user data offset (previous value of [u.pbase]) 28152 <1> ; ESI = pointer to file offset 28153 <1> ; EAX = system (I/O) buffer offset 28154 <1> ; ECX = byte count 28155 <1> ; EBX = system buffer (data) address 28156 <1> 28157 00005921 8B0D[CC6C0000] <1> mov ecx, [u.count] 28158 <1> ; mov u.count,r3 / move char count to r3 28159 <1> ; 08/02/2022 28160 00005927 31D2 <1> xor edx, edx 28161 00005929 B602 <1> mov dh, 2 28162 <1> ; edx = 512 28163 0000592B 39D1 <1> cmp ecx, edx ; 512 28164 <1> ;cmp ecx, 512 28165 <1> ; cmp r3,$512. / more than 512. char? 28166 0000592D 7602 <1> jna short dioreg_0 28167 <1> ; blos 1f / no, branch 28168 0000592F 89D1 <1> mov ecx, edx ; 512 28169 <1> ;mov ecx, 512 28170 <1> ; mov $512.,r3 / yes, just take 512. 28171 <1> dioreg_0: 28172 <1> ; 09/06/2015 28173 00005931 663B0D[106D0000] <1> cmp cx, [u.pcount] 28174 00005938 7607 <1> jna short dioreg_1 28175 0000593A 668B0D[106D0000] <1> mov cx, [u.pcount] 28176 <1> dioreg_1: 28177 <1> ; 1: 28178 00005941 8B15[C86C0000] <1> mov edx, [u.base] ; 09/06/2015 (eax -> edx) 28179 <1> ; mov u.base,r2 / put users base in r2 28180 00005947 010D[D06C0000] <1> add [u.nread], ecx 28181 <1> ; add r3,u.nread / add the number to be read to u.nread 28182 0000594D 290D[CC6C0000] <1> sub [u.count], ecx 28183 <1> ; sub r3,u.count / update count 28184 00005953 010D[C86C0000] <1> add [u.base], ecx 28185 <1> ; add r3,u.base / update base 28186 <1> ; 10/07/2015 28187 <1> ; Retro UNIX 386 v1 - modification ! 28188 <1> ; (File pointer points to byte position, not block/sector no.) 28189 <1> ; (It will point to next byte position instead of next block no.) 28190 00005959 8B35[B86C0000] <1> mov esi, [u.fofp] ; u.fopf points to byte position pointer 28191 0000595F 8B06 <1> mov eax, [esi] ; esi points to current byte pos. on the disk 28192 <1> ; 19/07/2022 28193 <1> ;add [esi], ecx ; ecx is added to set the next byte position 28194 00005961 25FF010000 <1> and eax, 1FFh ; get offset from beginning of current block 28195 <1> ;mov esi, ebx ; beginning of data in sector/block buffer 28196 <1> ;add esi, eax ; esi contains start address of the transfer 28197 <1> ; 19/07/2022 28198 00005966 01D8 <1> add eax, ebx ; eax contains start address of the transfer 28199 <1> ; 09/06/2015 - 10/07/2015 28200 00005968 66290D[106D0000] <1> sub [u.pcount], cx 28201 0000596F 81E2FF0F0000 <1> and edx, PAGE_OFF ; 0FFFh 28202 00005975 8B3D[0C6D0000] <1> mov edi, [u.pbase] 28203 0000597B 81E700F0FFFF <1> and edi, ~PAGE_OFF 28204 00005981 01D7 <1> add edi, edx 28205 00005983 893D[0C6D0000] <1> mov [u.pbase], edi 28206 00005989 010D[0C6D0000] <1> add [u.pbase], ecx ; 14/07/2015 28207 0000598F C3 <1> retn 28208 <1> ; rts r0 / return 28209 <1> 28210 <1> dskrd: 28211 <1> ; 15/07/2022 28212 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28213 <1> ; 08/02/2022 (Retro UNIX 386 v1.2) 28214 <1> ; 18/08/2015 28215 <1> ; 02/07/2015 28216 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 28217 <1> ; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 28218 <1> ; 28219 <1> ; 'dskrd' acquires an I/O buffer, puts in the proper 28220 <1> ; I/O queue entries (via bufaloc) then reads a block 28221 <1> ; (number specified in r1) in the acquired buffer.) 28222 <1> ; If the device is busy at the time dskrd is called, 28223 <1> ; dskrd calls idle. 28224 <1> ; 28225 <1> ; INPUTS -> 28226 <1> ; r1 - block number 28227 <1> ; cdev - current device number 28228 <1> ; OUTPUTS -> 28229 <1> ; r5 - points to first data word in I/O buffer 28230 <1> ; 28231 <1> ; ((AX = R1)) input/output 28232 <1> ; ((BX = R5)) output 28233 <1> ; 28234 <1> ; ((Modified registers: edx, ecx, ebx, esi, edi)) 28235 <1> ; 28236 00005990 E8BA000000 <1> call bufaloc 28237 <1> ; jsr r0,bufaloc / shuffle off to bufaloc; 28238 <1> ; / get a free I/O buffer 28239 <1> ;;jc error ; 20/07/2013 28240 00005995 740C <1> jz short dskrd_1 ; Retro UNIX 8086 v1 modification 28241 <1> ; br 1f / branch if block already in a I/O buffer 28242 <1> 28243 <1> ; 15/07/2022 28244 <1> ; (buffer header byte 1, bit 2 is disk read bit/flag) 28245 <1> dskrd_0: 28246 <1> ; 10/07/2015 (wslot) 28247 00005997 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 28248 <1> ; bis $2000,(r5) / set bit 10 of word 1 of 28249 <1> ; / I/O queue entry for buffer 28250 0000599C E893000000 <1> call poke 28251 <1> ; jsr r0,poke / just assigned in bufaloc, 28252 <1> ; / bit 10=1 says read 28253 <1> ; 09/06/2015 28254 <1> ;jnc short dskrd_1 28255 <1> ;mov dword [u.error], ERR_DRV_READ ; disk read error ! 28256 <1> ;jmp error 28257 <1> ; 08/02/2022 28258 000059A1 7204 <1> jc short dskrd_3 28259 <1> dskrd_1: ; 1: 28260 <1> ; 15/07/2022 28261 <1> ; 28262 <1> ; ;clr *$ps 28263 <1> ;test word [ebx], 2400h 28264 <1> ; ; bit $22000,(r5) / if either bits 10, or 13 are 1; 28265 <1> ; ; / jump to idle 28266 <1> ;jz short dskrd_2 28267 <1> ; ; beq 1f 28268 <1> ;;;mov ecx, [s.wait_] 28269 <1> ;call idle 28270 <1> ; ; jsr r0,idle; s.wait+2 28271 <1> ;jmp short dskrd_1 28272 <1> ; ; br 1b 28273 <1> dskrd_2: ; 1: 28274 000059A3 83C308 <1> add ebx, 8 28275 <1> ; add $8,r5 / r5 points to first word of data in block 28276 <1> ; / just read in 28277 000059A6 C3 <1> retn 28278 <1> ; rts r0 28279 <1> dskrd_err: 28280 <1> ; 08/02/2022 28281 <1> ; (jump from 'bread' error) 28282 <1> dskrd_3: 28283 <1> ; 08/02/2022 28284 000059A7 803D[176D0000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 28285 000059AE 7509 <1> jne short dskrd_4 ; no 28286 <1> ; yes, clear [u.brwdev] for next check and jump to 'error' 28287 000059B0 C605[176D0000]00 <1> mov byte [u.brwdev], 0 28288 000059B7 EB0A <1> jmp short dskrd_5 28289 <1> dskrd_4: 28290 000059B9 C705[186D0000]1100- <1> mov dword [u.error], ERR_DRV_READ ; disk read error ! 28291 000059C1 0000 <1> 28292 <1> dskrd_5: 28293 000059C3 E99DD7FFFF <1> jmp error 28294 <1> 28295 <1> bwslot: 28296 <1> ; 15/07/2022 28297 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28298 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 28299 <1> ; 10/07/2015 28300 <1> ; If the block/sector is not placed in a buffer 28301 <1> ; before 'wslot', it must be read before 28302 <1> ; it is written! (Otherwise transfer counts less 28303 <1> ; than 512 bytes will be able to destroy existing 28304 <1> ; data on disk.) 28305 <1> ; 28306 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 28307 <1> ; 26/04/2013(Retro UNIX 8086 v1) 28308 <1> ; Retro UNIX 8086 v1 modification ! 28309 <1> ; ('bwslot' will be called from 'bwrite' only!) 28310 <1> ; INPUT -> EDI - points to device id (in u.brwdev) 28311 <1> ; -> EAX = block number 28312 <1> ; 28313 000059C8 E88F000000 <1> call bufaloc_0 28314 000059CD 742A <1> jz short wslot_0 ; block/sector already is in the buffer 28315 <1> ; 12/01/2022 28316 <1> ; ebx = buffer header address 28317 <1> bwslot_0: 28318 <1> ; 10/07/2015 28319 000059CF 8B35[B86C0000] <1> mov esi, [u.fofp] 28320 000059D5 8B06 <1> mov eax, [esi] 28321 000059D7 25FF010000 <1> and eax, 1FFh ; offset from beginning of the sector/block 28322 000059DC 750C <1> jnz short bwslot_1 ; it is not a full sector write 28323 <1> ; recent disk data must be placed in the buffer 28324 000059DE 813D[CC6C0000]0002- <1> cmp dword [u.count], 512 28325 000059E6 0000 <1> 28326 000059E8 730F <1> jnb short wslot_0 28327 <1> bwslot_1: 28328 000059EA E8A8FFFFFF <1> call dskrd_0 28329 <1> ; 12/01/2022 28330 <1> ; ebx = buffer data address = buffer header addr + 8 28331 000059EF 83EB08 <1> sub ebx, 8 ; set ebx to the buffer header address again 28332 000059F2 EB05 <1> jmp short wslot_0 28333 <1> 28334 <1> wslot: 28335 <1> ; 16/07/2022 28336 <1> ; 15/07/2022 28337 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28338 <1> ; 28339 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 28340 <1> ; (32 bit modifications) 28341 <1> ; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1) 28342 <1> ; 28343 <1> ; 'wslot' calls 'bufaloc' and obtains as a result, a pointer 28344 <1> ; to the I/O queue of an I/O buffer for a block structured 28345 <1> ; device. It then checks the first word of I/O queue entry. 28346 <1> ; If bits 10 and/or 13 (read bit, waiting to read bit) are set, 28347 <1> ; wslot calls 'idle'. When 'idle' returns, or if bits 10 28348 <1> ; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first 28349 <1> ; word of the I/O queue entry (write bit, inhibit bit). 28350 <1> ; 28351 <1> ; INPUTS -> 28352 <1> ; r1 - block number 28353 <1> ; cdev - current (block/disk) device number 28354 <1> ; 28355 <1> ; OUTPUTS -> 28356 <1> ; bufp - bits 9 and 15 are set, 28357 <1> ; the remainder of the word left unchanged 28358 <1> ; r5 - points to first data word in I/O buffer 28359 <1> ; 28360 <1> ; ((AX = R1)) input/output 28361 <1> ; ((BX = R5)) output 28362 <1> ; 28363 <1> ; ((Modified registers: edx, ecx, ebx, esi, edi)) 28364 <1> 28365 000059F4 E856000000 <1> call bufaloc 28366 <1> ; 10/07/2015 28367 <1> ; jsr r0,bufaloc / get a free I/O buffer; pointer to first 28368 <1> ; br 1f / word in buffer in r5 28369 <1> ; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment) 28370 <1> ; EAX = Block/Sector number (r1) 28371 <1> wslot_0: ;1: 28372 <1> ; 15/07/2022 28373 <1> ; 28374 <1> ;test word [ebx], 2400h 28375 <1> ; ; bit $22000,(r5) / check bits 10, 13 (read, waiting to read) 28376 <1> ; ; / of I/O queue entry 28377 <1> ;jz short wslot_1 28378 <1> ; ; beq 1f / branch if 10, 13 zero (i.e., not reading, 28379 <1> ; ; / or not waiting to read) 28380 <1> ; 28381 <1> ;;mov ecx, [s.wait_] ; 29/07/2013 28382 <1> ;call idle 28383 <1> ; ; jsr r0,idle; / if buffer is reading or writing to read, 28384 <1> ; ; / idle 28385 <1> ;jmp short wslot_0 28386 <1> ; ; br 1b / till finished 28387 <1> wslot_1: ;1: 28388 <1> ;or word [ebx], 8200h 28389 <1> ; ; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue 28390 <1> ; ; / (write, inhibit bits) 28391 <1> ; ; clr *$ps / clear processor status 28392 <1> 28393 <1> ; 16/07/2022 28394 <1> ;dskwr_1: ; 09/03/2022 28395 <1> ;add ebx, 8 ; 11/06/2015 28396 <1> ; add $8,r5 / r5 points to first word in data area 28397 <1> ; / for this block 28398 <1> ; 15/07/2022 28399 <1> ; (set disk write bit/flag) 28400 <1> ;or word [ebx], 200h 28401 000059F9 43 <1> inc ebx 28402 000059FA 800B02 <1> or byte [ebx], 2 28403 000059FD 83C307 <1> add ebx, 7 28404 <1> ; 16/07/2022 28405 <1> dskwr_1: ; 08/02/2022 28406 00005A00 C3 <1> retn 28407 <1> ; rts r0 28408 <1> dskwr: 28409 <1> ; 16/07/2022 28410 <1> ; 15/07/2022 28411 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28412 <1> ; 09/03/2022 28413 <1> ; 08/02/2022 (Retro UNIX 386 v1.2) 28414 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 28415 <1> ; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1) 28416 <1> ; 28417 <1> ; 'dskwr' writes a block out on disk, via ppoke. The only 28418 <1> ; thing dskwr does is clear bit 15 in the first word of I/O queue 28419 <1> ; entry pointed by 'bufp'. 'wslot' which must have been called 28420 <1> ; previously has supplied all the information required in the 28421 <1> ; I/O queue entry. 28422 <1> ; 28423 <1> ; (Modified registers: ebx, ecx, edx, esi, edi) 28424 <1> ; 28425 00005A01 8B1D[346C0000] <1> mov ebx, [bufp] 28426 00005A07 668123FF7F <1> and word [ebx], 7FFFh ; 0111111111111111b 28427 <1> ; bic $100000,*bufp / clear bit 15 of I/O queue entry at 28428 <1> ; / bottom of queue 28429 00005A0C E823000000 <1> call poke 28430 <1> ; 09/06/2015 28431 00005A11 73ED <1> jnc short dskwr_1 ; 16/07/2022 28432 <1> ; ebx = buffer header ; 09/03/2022 28433 <1> ; 08/02/2022 28434 00005A13 803D[176D0000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 28435 00005A1A 7509 <1> jne short dskwr_0 ; no 28436 <1> ; yes, clear [u.brwdev] for next check and jump to 'error' 28437 00005A1C C605[176D0000]00 <1> mov byte [u.brwdev], 0 28438 00005A23 EB0A <1> jmp short dskwr_2 28439 <1> dskwr_0: 28440 00005A25 C705[186D0000]1200- <1> mov dword [u.error], ERR_DRV_WRITE ; disk write error ! 28441 00005A2D 0000 <1> 28442 <1> dskwr_2: 28443 00005A2F E931D7FFFF <1> jmp error 28444 <1> ;dskwr_1: 28445 <1> ; add ebx, 8 ; 09/03/2022 28446 <1> ; ; ebx = buffer data address 28447 <1> ; retn 28448 <1> 28449 <1> ;ppoke: 28450 <1> ; mov $340,*$ps 28451 <1> ; jsr r0,poke 28452 <1> ; clr *$ps 28453 <1> ; rts r0 28454 <1> 28455 <1> poke: 28456 <1> ; 15/07/2022 28457 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28458 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 28459 <1> ; 14/07/2022 28460 <1> ; ! Major Modification ! 28461 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 28462 <1> ; 28463 <1> ; 04/02/2022 (32 bit reg push pop) 28464 <1> ; 24/10/2015 28465 <1> ; 20/08/2015 28466 <1> ; 18/08/2015 28467 <1> ; 02/07/2015 28468 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 28469 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 28470 <1> ; 28471 <1> ; (NOTE: There are some disk I/O code modifications & extensions 28472 <1> ; & exclusions on original 'poke' & other device I/O procedures of 28473 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 28474 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 28475 <1> ; 28476 <1> ; Basic I/O functions for all block structured devices 28477 <1> ; 28478 <1> ; (Modified registers: ECX, EDX, ESI, EDI) 28479 <1> ; 28480 <1> ; 20/07/2013 modifications 28481 <1> ; (Retro UNIX 8086 v1 features only !) 28482 <1> ; INPUTS -> 28483 <1> ; EBX = buffer header address 28484 <1> ; OUTPUTS -> 28485 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 28486 <1> ; cf=1 -> error, word [EBX] = 0FFFFh 28487 <1> ; (drive not ready or r/w error!) 28488 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 28489 <1> ; (dword [EBX+4] = 0FFFFFFFFh means RW/IO error) 28490 <1> ; (also it indicates invalid buffer data) 28491 <1> 28492 <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 28493 <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 28494 <1> ; Buffer header: 28495 <1> ; byte 0 - device/disk (index) number 28496 <1> ; byte 1 - status 28497 <1> ; before 'poke' 28498 <1> ; bit 0 - valid bit 28499 <1> ; (0 for new buffer) 28500 <1> ; (1 for existing buffer) 28501 <1> ; bit 1 - write (modified) bit, disk write flag 28502 <1> ; bit 2 - read bit, disk read flag 28503 <1> ; after 'poke' 28504 <1> ; if disk r/w is successed 28505 <1> ; bit 0 = 1 28506 <1> ; bit 1 = 0 28507 <1> ; bit 2 = 0 28508 <1> ; if disk r/w is failed 28509 <1> ; bit 0 = 0 (invalid buffer) 28510 <1> ; bit 1 = 0 (write bit) 28511 <1> ; bit 2 = 0 (read bit) 28512 <1> ; 28513 <1> ; byte 2 & byte 3 - not used 28514 <1> ; byte 4 to byte 7 - disk block/sector address 28515 <1> 28516 <1> ; 04/02/2022 28517 00005A34 50 <1> push eax 28518 00005A35 E896000000 <1> call diskio ; Retro UNIX 8086 v1 Only ! 28519 00005A3A 58 <1> pop eax 28520 00005A3B 730D <1> jnc short seta ; 14/07/2022 28521 <1> 28522 <1> ; 14/07/2022 28523 <1> ; (invalidate buffer) 28524 <1> 28525 <1> ; 02/07/2015 (32 bit modification) 28526 <1> ; 20/07/2013 28527 00005A3D C74304FFFFFFFF <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 28528 <1> ; mov $-1,2(r1) / destroy associativity 28529 00005A44 66C703FF00 <1> mov word [ebx], 0FFh ; 20/08/2015 28530 <1> ; clrb 1(r1) / do not do I/O 28531 <1> ;stc 28532 00005A49 C3 <1> retn 28533 <1> ; rts r0 28534 <1> seta: 28535 00005A4A C6430101 <1> mov byte [ebx+1], 1 ; clear write/read bits, set valid bit 28536 <1> ;clc 28537 00005A4E C3 <1> retn 28538 <1> 28539 <1> %if 0 28540 <1> 28541 <1> poke: 28542 <1> ; 29/11/2021 (32 bit reg push-pop) 28543 <1> ; 24/10/2015 28544 <1> ; 20/08/2015 28545 <1> ; 18/08/2015 28546 <1> ; 02/07/2015 28547 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 28548 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 28549 <1> ; 28550 <1> ; (NOTE: There are some disk I/O code modifications & extensions 28551 <1> ; & exclusions on original 'poke' & other device I/O procedures of 28552 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 28553 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 28554 <1> ; 28555 <1> ; Basic I/O functions for all block structured devices 28556 <1> ; 28557 <1> ; (Modified registers: ecx, edx, esi, edi) 28558 <1> ; 28559 <1> ; 20/07/2013 modifications 28560 <1> ; (Retro UNIX 8086 v1 features only !) 28561 <1> ; INPUTS -> 28562 <1> ; (EBX = buffer header address) 28563 <1> ; OUTPUTS -> 28564 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 28565 <1> ; cf=1 -> error, word [EBX] = 0FFFFh 28566 <1> ; (drive not ready or r/w error!) 28567 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 28568 <1> ; (dword [EBx+4] = 0FFFFFFFFh means RW/IO error) 28569 <1> ; (also it indicates invalid buffer data) 28570 <1> ; 28571 <1> push ebx 28572 <1> ; mov r1,-(sp) 28573 <1> ; mov r2,-(sp) 28574 <1> ; mov r3,-(sp) 28575 <1> push eax ; Physical Block Number (r1) (mget) 28576 <1> ; 28577 <1> ; 09/06/2015 28578 <1> ; (permit read/write after a disk R/W error) 28579 <1> mov cl, [ebx] ; device id (0 to 5) 28580 <1> mov al, 1 28581 <1> shl al, cl 28582 <1> test al, [active] ; busy ? (error) 28583 <1> jz short poke_0 28584 <1> not al 28585 <1> and [active], al ; reset busy bit for this device only 28586 <1> poke_0: 28587 <1> mov esi, bufp + (4*(nbuf+2)) 28588 <1> ; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority 28589 <1> ; / I/O queue pointer 28590 <1> poke_1: ; 1: 28591 <1> sub esi, 4 28592 <1> mov ebx, [esi] 28593 <1> ; mov -(r2),r1 / r1 points to an I/O queue entry 28594 <1> mov ax, [ebx] ; 17/07/2013 28595 <1> test ah, 06h 28596 <1> ;test word [ebx], 600h ; 0000011000000000b 28597 <1> ; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 28598 <1> ; / queue entry 28599 <1> jz short poke_5 28600 <1> ; beq 2f / branch to 2f if both are clear 28601 <1> ; 31/07/2013 28602 <1> ;test ah, 0B0h ; (*) 28603 <1> ;;test word [ebx], 0B000h ; 1011000000000000b 28604 <1> ; bit $130000,(r1) / test bits 12, 13, and 15 28605 <1> ;jnz short poke_5 ; 31/07/2013 (*) 28606 <1> ; bne 2f / branch if any are set 28607 <1> ;movzx ecx, byte [ebx] ; 09/06/2015 ; Device Id 28608 <1> ; movb (r1),r3 / get device id 28609 <1> movzx ecx, al ; 18/08/2015 28610 <1> ;mov edi, ecx ; 26/04/2013 28611 <1> xor eax, eax ; 0 28612 <1> ;cmp [edi+drv.error], al ; 0 28613 <1> ; tstb deverr(r3) / test for errors on this device 28614 <1> ;jna short poke_2 28615 <1> ; beq 3f / branch if no errors 28616 <1> ; 02/07/2015 28617 <1> ;dec eax 28618 <1> ;mov [ebx+4], ax ; 0FFFFFFFFh ; -1 28619 <1> ; mov $-1,2(r1) / destroy associativity 28620 <1> ;shr eax, 24 28621 <1> ;mov [ebx], eax ; 000000FFh, reset 28622 <1> ; clrb 1(r1) / do not do I/O 28623 <1> ;jmp short poke_5 28624 <1> ; ; br 2f 28625 <1> ; rts r0 28626 <1> poke_2: ; 3: 28627 <1> ; 02/07/2015 28628 <1> inc cl ; 0FFh -> 0 28629 <1> jz short poke_5 28630 <1> inc al ; mov ax, 1 28631 <1> dec cl 28632 <1> jz short poke_3 28633 <1> ; 26/04/2013 Modification 28634 <1> ;inc al ; mov ax, 1 28635 <1> ;or cl, cl ; Retro UNIX 8086 v1 device id. 28636 <1> ;jz short poke_3 ; cl = 0 28637 <1> shl al, cl ; shl ax, cl 28638 <1> poke_3: 28639 <1> ;test [active], ax 28640 <1> test [active], al 28641 <1> ; bit $2,active / test disk busy bit 28642 <1> jnz short poke_5 28643 <1> ; bne 2f / branch if bit is set 28644 <1> ;or [active], ax 28645 <1> or [active], al 28646 <1> ; bis $2,active / set disk busy bit 28647 <1> push eax ; 29/11/2021 28648 <1> call diskio ; Retro UNIX 8086 v1 Only ! 28649 <1> ;mov [edi+drv.error], ah 28650 <1> pop eax 28651 <1> jnc short poke_4 ; 20/07/2013 28652 <1> ;cmp [edi+drv.error], al ; 0 28653 <1> ;jna short poke_4 28654 <1> ; tstb deverr(r3) / test for errors on this device 28655 <1> ; beq 3f / branch if no errors 28656 <1> ; 02/07/2015 (32 bit modification) 28657 <1> ; 20/07/2013 28658 <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 28659 <1> ; mov $-1,2(r1) / destroy associativity 28660 <1> mov word [ebx], 0FFh ; 20/08/2015 28661 <1> ; clrb 1(r1) / do not do I/O 28662 <1> jmp short poke_5 28663 <1> poke_4: ; 20/07/2013 28664 <1> ; 17/07/2013 28665 <1> not al 28666 <1> and [active], al ; reset, not busy 28667 <1> ; EBX = system I/O buffer header (queue entry) address 28668 <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits. 28669 <1> mov ax, [ebx] 28670 <1> ; mov (r1),r3 / move word 1 of I/O queue entry into r3 28671 <1> and ax, 600h 28672 <1> ; bic $!3000,r3 / clear all bits except 9 and 10 28673 <1> and word [ebx], 0F9FFh 28674 <1> ; bic $3000,(r1) / clear only bits 9 and 10 28675 <1> shl ah, 3 28676 <1> ; rol r3 28677 <1> ; rol r3 28678 <1> ; rol r3 28679 <1> or [ebx], ax 28680 <1> ; bis r3,(r1) / or old value of bits 9 and 10 with 28681 <1> ; bits 12 and 13 28682 <1> call idle ; 18/01/2014 28683 <1> ;; sti 28684 <1> ;hlt ; wait for a hardware interrupt 28685 <1> ;; cli 28686 <1> ; NOTE: In fact, disk controller's 'disk I/O completed' 28687 <1> ; interrupt would be used to reset busy bits, but INT 13h 28688 <1> ; returns when disk I/O is completed. So, here, as temporary 28689 <1> ; method, this procedure will wait for a time according to 28690 <1> ; multi tasking and time sharing concept. 28691 <1> ; 28692 <1> ; 24/10/2015 28693 <1> ;not ax 28694 <1> mov ax, 0FFh ; 24/10/2015 (temporary) 28695 <1> and [ebx], ax ; clear bits 12 and 13 28696 <1> poke_5: ;2: 28697 <1> cmp esi, bufp 28698 <1> ; cmp r2,$bufp / test to see if entire I/O queue 28699 <1> ; / has been scanned 28700 <1> ja short poke_1 28701 <1> ; bhi 1b 28702 <1> ; 24/03/2013 28703 <1> ; mov (sp)+,r3 28704 <1> ; mov (sp)+,r2 28705 <1> ; mov (sp)+,r1 28706 <1> pop eax ; Physical Block Number (r1) (mget) 28707 <1> pop ebx 28708 <1> ; 02/07/2015 (32 bit modification) 28709 <1> ; 20/07/2013 28710 <1> ;cmp dword [ebx+4], 0FFFFFFFFh 28711 <1> cmp byte [ebx], 0FFh ; 20/08/2015 28712 <1> ; 28713 <1> ; 'poke' returns with cf=0 if the requested buffer is read 28714 <1> ; or written successfully; even if an error occurs while 28715 <1> ; reading to or writing from other buffers. 20/07/2013 28716 <1> ; 28717 <1> ; 09/06/2015 28718 <1> cmc 28719 <1> retn 28720 <1> ; rts r0 28721 <1> 28722 <1> %endif 28723 <1> 28724 <1> bufaloc: 28725 <1> ; 15/07/2022 28726 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28727 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 28728 <1> ; 20/08/2015 28729 <1> ; 19/08/2015 28730 <1> ; 02/07/2015 28731 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 28732 <1> ; (32 bit modifications) 28733 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 28734 <1> ; 28735 <1> ; bufaloc - Block device I/O buffer allocation 28736 <1> ; 28737 <1> ; INPUTS -> 28738 <1> ; r1 - block number 28739 <1> ; cdev - current (block/disk) device number 28740 <1> ; bufp+(2*n)-2 --- n = 1 ... nbuff 28741 <1> ; OUTPUTS -> 28742 <1> ; r5 - pointer to buffer allocated 28743 <1> ; bufp ... bufp+12 --- (bufp), (bufp)+2 28744 <1> ; 28745 <1> ; ((AX = R1)) input/output 28746 <1> ; ((BX = R5)) output 28747 <1> ; ((Modified registers: DX, CX, BX, SI, DI, BP)) 28748 <1> ; zf=1 -> block already in a I/O buffer 28749 <1> ; zf=0 -> a new I/O buffer has been allocated 28750 <1> ; ((DL = Device ID)) 28751 <1> ; (((DH = 0 or 1))) 28752 <1> ; (((CX = previous value of word ptr [bufp]))) 28753 <1> ; ((CX and DH will not be used after return))) 28754 <1> 28755 <1> ; 15/07/2022 28756 <1> ; Modified registers: EBX, ECX, EDX, ESI, EDI 28757 <1> 28758 <1> ;;push esi ; *** 28759 <1> ; mov r2,-(sp) / save r2 on stack 28760 <1> ; mov $340,*$ps / set processor priority to 7 28761 <1> ; 20/07/2013 28762 <1> ; 26/04/2013 28763 <1> ;movzx ebx, byte [cdev] ; 0 or 1 28764 <1> ;mov edi, rdev ; offset mdev = offset rdev + 1 28765 <1> ;add edi, ebx 28766 <1> ; 09/01/2022 28767 00005A4F 0FB63D[816C0000] <1> movzx edi, byte [cdev] ; 0 or 1 28768 00005A56 81C7[826C0000] <1> add edi, rdev 28769 <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !! 28770 <1> ;; EDI points to device id. 28771 00005A5C 0FB61F <1> movzx ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev 28772 <1> ; 11/06/2021 28773 00005A5F 80BB[AE620000]F0 <1> cmp byte [ebx+drv.status], 0F0h ; Drive not ready ! 28774 00005A66 720F <1> jb short bufaloc_9 28775 00005A68 C705[186D0000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY 28776 00005A70 0000 <1> 28777 00005A72 E9EED6FFFF <1> jmp error 28778 <1> bufaloc_9: 28779 00005A77 89DA <1> mov edx, ebx ; dh = 0, dl = device number (0 to 5) 28780 <1> bufaloc_10: ; 02/07/2015 28781 <1> ; 14/07/2022 28782 <1> ;xor ebp, ebp ; 0 28783 <1> ;push ebp ; 0 28784 <1> ;mov ebp, esp 28785 00005A79 31FF <1> xor edi, edi ; 0 28786 00005A7B 57 <1> push edi 28787 <1> bufaloc_1: ;1: 28788 <1> ; clr -(sp) / vacant buffer 28789 00005A7C BE[346C0000] <1> mov esi, bufp 28790 <1> ; mov $bufp,r2 / bufp contains pointers to I/O queue 28791 <1> ; / entrys in buffer area 28792 <1> bufaloc_2: ;2: 28793 00005A81 8B1E <1> mov ebx, [esi] 28794 <1> ; mov (r2)+,r5 / move pointer to word 1 of an I/O 28795 <1> ; queue entry into r5 28796 <1> ; 15/07/2022 28797 00005A83 8B0B <1> mov ecx, [ebx] 28798 <1> ;test word [ebx], 0F600h 28799 <1> ; 15/07/2022 28800 00005A85 F6C501 <1> test ch, 1 ; valid buffer (content) ? 28801 <1> ; bit $173000,(r5) / lock+keep+active+outstanding 28802 00005A88 7505 <1> jnz short bufaloc_3 ; yes 28803 <1> ; bne 3f / branch when 28804 <1> ; / any of bits 9,10,12,13,14,15 are set 28805 <1> ; / (i.e., buffer busy) 28806 <1> ;mov [ebp], esi ; pointer to I/0 queue entry 28807 <1> ; 15/07/2022 28808 <1> ; save free buffer pointer 28809 00005A8A 893424 <1> mov [esp], esi 28810 <1> ; mov r2,(sp) ;/ save pointer to last non-busy buffer 28811 <1> ; / found points to word 2 of I/O queue entry) 28812 <1> ; continue to see if requested sector/block buffer 28813 <1> ; already is one of existing (valid) buffers 28814 <1> ;jmp short bufaloc_4 28815 00005A8D EB0E <1> jmp short bufaloc_11 ; 15/07/2022 28816 <1> bufaloc_3: ;3: 28817 <1> ;mov dl, [edi] ; 26/04/2013 28818 <1> ; 28819 00005A8F 38D1 <1> cmp cl, dl ; 15/07/2022 28820 <1> ;cmp [ebx], dl 28821 <1> ; cmpb (r5),cdev / is device in I/O queue entry same 28822 <1> ; / as current device 28823 00005A91 7508 <1> jne short bufaloc_4 28824 <1> ; bne 3f 28825 00005A93 394304 <1> cmp [ebx+4], eax 28826 <1> ; cmp 2(r5),r1 / is block number in I/O queue entry, 28827 <1> ; / same as current block number 28828 00005A96 7503 <1> jne short bufaloc_4 28829 <1> ; bne 3f 28830 <1> ;add esp, 4 28831 00005A98 59 <1> pop ecx 28832 <1> ; tst (sp)+ / bump stack pointer 28833 00005A99 EB1D <1> jmp short bufaloc_7 ; Retro Unix 8086 v1 modification 28834 <1> ; jump to bufaloc_6 in original Unix v1 28835 <1> ; br 1f / use this buffer 28836 <1> bufaloc_4: ;3: 28837 <1> ; 15/07/2022 28838 <1> ; save last valid buffer 28839 <1> ; (will be used if there is not a free buffer) 28840 00005A9B 89F7 <1> mov edi, esi 28841 <1> bufaloc_11: 28842 00005A9D 83C604 <1> add esi, 4 ; 20/08/2015 28843 <1> ; 28844 00005AA0 81FE[746C0000] <1> cmp esi, bufp + (nbuf*4) 28845 <1> ; cmp r2,$bufp+nbuf+nbuf 28846 00005AA6 72D9 <1> jb short bufaloc_2 28847 <1> ; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all 28848 <1> ; / buffers not checked) 28849 00005AA8 5E <1> pop esi 28850 <1> ; mov (sp)+,r2 / once all bufs are examined move pointer 28851 <1> ; / to last free block 28852 00005AA9 09F6 <1> or esi, esi 28853 00005AAB 7502 <1> jnz short bufaloc_5 28854 <1> ; bne 2f / if (sp) is non zero, i.e., 28855 <1> ; / if a free buffer is found branch to 2f 28856 <1> 28857 <1> ; 15/07/2022 28858 <1> ; if there is not a free buffer 28859 <1> ; we can use last valid buffer (the oldest buffer) 28860 <1> ; ((ptr to new buffer is located at head of buff ptr chain)) 28861 00005AAD 89FE <1> mov esi, edi 28862 <1> 28863 <1> ;;mov ecx, [s.wait_] 28864 <1> ;call idle 28865 <1> ; ; jsr r0,idle; s.wait+2 / idle if no free buffers 28866 <1> ;jmp short bufaloc_10 ; 02/07/2015 28867 <1> ; ; br 1b 28868 <1> bufaloc_5: ;2: 28869 <1> ; tst (r0)+ / skip if warmed over buffer 28870 <1> ; 15/07/2022 28871 <1> ;inc dh ; Retro UNIX 8086 v1 modification 28872 <1> bufaloc_6: ;1: 28873 00005AAF 8B1E <1> mov ebx, [esi] 28874 <1> ; mov -(r2),r5 / put pointer to word 1 of I/O queue 28875 <1> ; / entry in r5 28876 <1> ;; 26/04/2013 28877 <1> ;;mov dl, [edi] ; byte [rdev] or byte [mdev] 28878 <1> ;mov [ebx], dl 28879 <1> ; movb cdev,(r5) / put current device number 28880 <1> ; / in I/O queue entry 28881 <1> ; 15/07/2022 28882 <1> ; invalidate buffer before r/w (new) disk sector/block 28883 <1> ;mov [ebx+1], dh ; 0 28884 <1> ; 15/07/2022 28885 00005AB1 8913 <1> mov [ebx], edx ; dh = 0 28886 <1> 28887 00005AB3 894304 <1> mov [ebx+4], eax 28888 <1> ; mov r1,2(r5) / move block number into word 2 28889 <1> ; / of I/O queue entry 28890 <1> ; 15/07/2022 28891 00005AB6 FEC6 <1> inc dh ; dh = 1 28892 <1> bufaloc_7: ;1: 28893 00005AB8 81FE[346C0000] <1> cmp esi, bufp 28894 <1> ; cmp r2,$bufp / bump all entrys in bufp 28895 <1> ; / and put latest assigned 28896 00005ABE 760B <1> jna short bufaloc_8 28897 <1> ; blos 1f / buffer on the top 28898 <1> ; / (this makes if the lowest priority) 28899 <1> ; 15/07/2022 28900 00005AC0 89F7 <1> mov edi, esi 28901 00005AC2 83EE04 <1> sub esi, 4 28902 00005AC5 8B0E <1> mov ecx, [esi] 28903 00005AC7 890F <1> mov [edi], ecx ; 15/07/2022 28904 <1> ;mov [esi+4], ecx 28905 <1> ; mov -(r2),2(r2) / job for a particular device 28906 00005AC9 EBED <1> jmp short bufaloc_7 28907 <1> ; br 1b 28908 <1> bufaloc_8: ;1: 28909 00005ACB 891E <1> mov [esi], ebx 28910 <1> ; mov r5,(r2) 28911 <1> ;;pop esi ; *** 28912 <1> ; mov (sp)+,r2 / restore r2 28913 00005ACD 08F6 <1> or dh, dh ; 0 or 1 ? 28914 <1> ; Retro UNIX 8086 v1 modification 28915 <1> ; zf=1 --> block already is in an I/O buffer 28916 <1> ; zf=0 --> a new I/O buffer has been allocated 28917 00005ACF C3 <1> retn 28918 <1> ; rts r0 28919 <1> 28920 <1> diskio: 28921 <1> ; 16/07/2022 28922 <1> ; 12/07/2022 - Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28923 <1> ; 08/07/2022 28924 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 28925 <1> ; ((simplified and shortened 'diskio.s' code)) 28926 <1> ; 12/02/2022 28927 <1> ; 10/02/2022 28928 <1> ; 08/02/2022 28929 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 28930 <1> ; 28/11/2021 28931 <1> ; 10/07/2015 28932 <1> ; 02/07/2015 28933 <1> ; 16/06/2015 28934 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 28935 <1> ; (80386 protected mode modifications) 28936 <1> ; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1) 28937 <1> ; 28938 <1> ; Retro UNIX 8086 v1 feature only ! 28939 <1> ; 28940 <1> ; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011) 28941 <1> ; 04/07/2009 - 20/07/2011 28942 <1> ; 28943 <1> ; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes) 28944 <1> ; 28945 <1> ; INPUTS -> 28946 <1> ; ebx = System I/O Buffer header address 28947 <1> ; 28948 <1> ; OUTPUTS -> cf=0 --> done 28949 <1> ; cf=1 --> error code in AH 28950 <1> ; ; 08/02/2022 28951 <1> ; cf=1 & [u.brwdev] = 0FFh --> 28952 <1> ; error code in [u.error] 28953 <1> ; 28954 <1> ; (Modified registers: eax, ecx, edx) 28955 <1> 28956 <1> ;rw_disk_sector: 28957 <1> ; 16/07/2022 28958 <1> ; 12/07/2022 28959 <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 28960 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 28961 <1> ; 12/02/2022 28962 <1> ; 10/02/2022 28963 <1> ; 08/02/2022 28964 <1> ; 28/11/2021 28965 <1> ; 10/07/2015 28966 <1> ; 02/07/2015 28967 <1> ; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 28968 <1> ; 21/02/2015 ('dsectpm.s', 'read_disk_sector') 28969 <1> ; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s') 28970 <1> ; 01/12/2014 - 18/01/2015 ('dsectrm2.s') 28971 <1> ; 28972 <1> ;;mov dx, 0201h ; Read 1 sector/block 28973 <1> ;mov dh, 2 28974 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 28975 00005AD0 B602 <1> mov dh, 2 ; Write 1 sector/block 28976 00005AD2 668B03 <1> mov ax, [ebx] 28977 <1> ; 28978 00005AD5 56 <1> push esi ; **** 28979 00005AD6 53 <1> push ebx ; *** 28980 <1> ; 28981 00005AD7 0FB6C8 <1> movzx ecx, al 28982 <1> ; 28/11/2021 28983 <1> ;mov ecx, eax 28984 00005ADA 89CE <1> mov esi, ecx 28985 <1> ; 28986 00005ADC 38F1 <1> cmp cl, dh ; 2 28987 00005ADE 7202 <1> jb short rwdsk0 28988 00005AE0 047E <1> add al, 7Eh ; 80h, 81h, 82h, 83h 28989 <1> rwdsk0: 28990 <1> ; 16/07/2022 28991 <1> ; 12/07/2022 28992 <1> ;mov [drv], al 28993 00005AE2 81C6[AE620000] <1> add esi, drv.status 28994 <1> ; 11/06/2015 28995 00005AE8 803EF0 <1> cmp byte [esi], 0F0h 28996 00005AEB 7204 <1> jb short rwdsk1 28997 <1> ; 'drive not ready' error 28998 <1> ; 10/02/2022 28999 <1> ; 08/02/2022 29000 <1> ;mov byte [u.brwdev], 0FFh ; error code in [u.error] 29001 <1> ;mov dword [u.error], ERR_DRV_NOT_RDY 29002 <1> ;;jmp error 29003 <1> ;stc ; cf = 1 29004 <1> ;retn 29005 <1> ; 10/02/2022 29006 00005AED B10F <1> mov cl, ERR_DRV_NOT_RDY 29007 00005AEF EB1F <1> jmp short rwdsk_err1 29008 <1> rwdsk1: 29009 <1> ; 16/07/2022 29010 <1> ;test ah, 2 29011 <1> ;;test ax, 200h ; Bit 9 of word 0 (status word) 29012 <1> ; ; write bit 29013 <1> ;jz short rwdsk2 29014 <1> 29015 <1> ;;test ah, 4 29016 <1> ;;;test ax, 400h ; Bit 10 of word 0 (status word) 29017 <1> ;; ; read bit 29018 <1> ;;jz short diskio_ret 29019 <1> 29020 <1> ;inc dh ; 03h = write 29021 <1> 29022 <1> ; 08/07/2022 29023 00005AF1 84F4 <1> test ah, dh ; test ah, 2 29024 00005AF3 7502 <1> jnz short rwdsk2 ; dh = 02h = write 29025 00005AF5 FECE <1> dec dh 29026 <1> ; dh = 01h = read 29027 <1> rwdsk2: 29028 00005AF7 88C2 <1> mov dl, al 29029 00005AF9 83C304 <1> add ebx, 4 ; sector/block address/number pointer 29030 00005AFC 8B03 <1> mov eax, [ebx] ; sector/block number (LBA) 29031 00005AFE C0E102 <1> shl cl, 2 29032 00005B01 81C1[92620000] <1> add ecx, drv.size ; disk size 29033 00005B07 3B01 <1> cmp eax, [ecx] ; Last sector + 1 (number of secs.) 29034 00005B09 7214 <1> jb short rwdsk3 29035 <1> ; 'out of volume' error 29036 <1> ; 10/02/2022 29037 <1> ; 08/02/2022 29038 <1> ;mov byte [u.brwdev], 0FFh ; error code in [u.error] 29039 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE 29040 <1> ;;jmp error 29041 <1> ;stc ; cf = 1 29042 <1> ;retn 29043 <1> ; 10/02/2022 29044 00005B0B B910000000 <1> mov ecx, ERR_DEV_VOL_SIZE 29045 <1> rwdsk_err1: 29046 00005B10 C605[176D0000]FF <1> mov byte [u.brwdev], 0FFh 29047 00005B17 890D[186D0000] <1> mov [u.error], ecx ; 12/02/2022 29048 00005B1D EB27 <1> jmp short rwdsk_err2 29049 <1> rwdsk3: 29050 <1> ; 11/06/2015 29051 00005B1F 83C304 <1> add ebx, 4 ; buffer address 29052 00005B22 C605[3B6D0000]04 <1> mov byte [retry_count], 4 29053 <1> ; 12/07/2022 29054 <1> ;test byte [esi], 1 ; LBA ready ? 29055 <1> ;jz short rwdsk_chs 29056 <1> rwdsk_lba: 29057 <1> ; LBA read/write (with private LBA function) 29058 <1> ;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan)) 29059 00005B29 83C607 <1> add esi, drv.error - drv.status ; 10/07/2015 29060 00005B2C 89C1 <1> mov ecx, eax ; sector number 29061 <1> ; ebx = buffer (data) address 29062 <1> ; dl = physical drive number (0, 1, 80h, 81h, 82h, 83h) 29063 <1> rwdsk_lba_retry: 29064 <1> ;mov dl, [drv] 29065 <1> ; Function 1Bh = LBA read, 1Ch = LBA write 29066 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 29067 <1> ;;mov ah, 1Ch - 03h ; LBA write function number - 3 29068 <1> ;mov ah, 2 ; LBA write function number - 2 29069 <1> ;add ah, dh 29070 <1> ;mov al, 1 29071 <1> ;int 13h 29072 <1> ;call int13h 29073 <1> ; 12/07/2022 29074 00005B2E 88F0 <1> mov al, dh ; function (1 or 2) 29075 <1> ; (1 = read, 2 = write ) 29076 <1> ; ecx = disk sector address (LBA) 29077 <1> ; ebx = buffer address 29078 <1> ; dl = (physical) disk number 29079 <1> ; al = function (r/w) 29080 00005B30 E831C4FFFF <1> call DISK_IO 29081 <1> 29082 00005B35 8826 <1> mov [esi], ah ; error code ; 10/07/2015 29083 00005B37 730E <1> jnc short rwdsk_lba_ok 29084 00005B39 80FC80 <1> cmp ah, 80h ; time out ? 29085 00005B3C 7408 <1> je short rwdsk_lba_fails 29086 00005B3E FE0D[3B6D0000] <1> dec byte [retry_count] 29087 00005B44 7504 <1> jnz short rwdsk_lba_reset ; 10/07/2015 29088 <1> rwdsk_err2: ; 10/02/2022 29089 <1> rwdsk_lba_fails: 29090 00005B46 F9 <1> stc 29091 <1> rwdsk_lba_ok: 29092 00005B47 5B <1> pop ebx ; *** 29093 00005B48 5E <1> pop esi ; **** 29094 00005B49 C3 <1> retn 29095 <1> rwdsk_lba_reset: 29096 <1> ;mov ah, 0Dh ; Alternate reset 29097 <1> ;int 13h 29098 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 29099 <1> ;mov ah, 5 ; Alternate reset 29100 <1> ;call int13h 29101 <1> ;jnc short rwdsk_lba_retry 29102 <1> ; 12/07/2022 29103 00005B4A 30C0 <1> xor al, al ; 0 ; reset 29104 00005B4C E815C4FFFF <1> call DISK_IO 29105 00005B51 73DB <1> jnc short rwdsk_lba_retry 29106 <1> 29107 00005B53 8826 <1> mov [esi], ah ; error code ; 10/07/2015 29108 00005B55 EBF0 <1> jmp short rwdsk_lba_ok 29109 <1> 29110 <1> ; 12/07/2022 29111 <1> ; (CHS Read/Write setup is not needed here.) 29112 <1> ; (LBA address will be converted to CHS parameters 29113 <1> ; in 'DISK_IO' procedure when/if it is required.) 29114 <1> 29115 <1> ; ; CHS read (convert LBA address to CHS values) 29116 <1> ;rwdsk_chs: 29117 <1> ; ; 10/07/2015 29118 <1> ; sub esi, drv.status 29119 <1> ; mov ecx, esi 29120 <1> ; add esi, drv.error 29121 <1> ; ; 02/07/2015 29122 <1> ; ; 16/06/2015 29123 <1> ; ; 11/06/2015 29124 <1> ; push ebx ; ** ; buffer 29125 <1> ; shl ecx, 1 29126 <1> ; push ecx ; * 29127 <1> ; ; 29128 <1> ; mov ebx, ecx 29129 <1> ; mov [rwdsk], dh ; 02/07/2015 29130 <1> ; xor edx, edx ; 0 29131 <1> ; ; 09/01/2022 29132 <1> ; ;sub ecx, ecx 29133 <1> ; add ebx, drv.spt 29134 <1> ; mov cx, [ebx] ; sector per track 29135 <1> ; ; EDX:EAX = LBA 29136 <1> ; div ecx 29137 <1> ; mov cl, dl ; sector number - 1 29138 <1> ; inc cl ; sector number (1 based) 29139 <1> ; pop ebx ; * ; 11/06/2015 29140 <1> ; ;push cx 29141 <1> ; ; 09/01/2022 29142 <1> ; push ecx 29143 <1> ; add ebx, drv.heads 29144 <1> ; mov cx, [ebx] ; heads 29145 <1> ; xor edx, edx 29146 <1> ; ; EAX = cylinders * heads + head 29147 <1> ; div ecx 29148 <1> ; ;pop cx ; sector number 29149 <1> ; ; 09/01/2022 29150 <1> ; pop ecx 29151 <1> ; mov dh, dl ; head number 29152 <1> ; mov dl, [drv] 29153 <1> ; mov ch, al ; cylinder (bits 0-7) 29154 <1> ; shl ah, 6 29155 <1> ; or cl, ah ; cylinder (bits 8-9) 29156 <1> ; ; sector (bits 0-7) 29157 <1> ; pop ebx ; ** ; buffer ; 11/06/2015 29158 <1> ; ; CL = sector (bits 0-5) 29159 <1> ; ; cylinder (bits 8-9 -> bits 6-7) 29160 <1> ; ; CH = cylinder (bits 0-7) 29161 <1> ; ; DH = head 29162 <1> ; ; DL = drive 29163 <1> ; ; 29164 <1> ; mov byte [retry_count], 4 29165 <1> ;rwdsk_retry: 29166 <1> ; ;mov ah, [rwdsk] ; 02h = read, 03h = write 29167 <1> ; ; 08/07/2022 29168 <1> ; mov ah, [rwdsk] ; 01h = read, 02h = write 29169 <1> ; mov al, 1 ; sector count 29170 <1> ; ;int 13h 29171 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 29172 <1> ; call int13h 29173 <1> ; mov [esi], ah ; error code ; 10/07/2015 29174 <1> ; jnc short rwdsk_ok ; ah = 0 29175 <1> ; cmp ah, 80h ; time out ? 29176 <1> ; je short rwdsk_fails 29177 <1> ; dec byte [retry_count] 29178 <1> ; jnz short rwdsk_reset 29179 <1> ;rwdsk_fails: 29180 <1> ; stc 29181 <1> ;rwdsk_ok: 29182 <1> ; pop ebx ; *** 29183 <1> ; pop esi ; **** 29184 <1> ; retn 29185 <1> ;rwdsk_reset: 29186 <1> ; ; 02/02/2015 29187 <1> ; sub ah, ah 29188 <1> ; cmp dl, 80h 29189 <1> ; jb short rwdsk_fd_reset 29190 <1> ; ;mov ah, 0Dh ; Alternate reset 29191 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 29192 <1> ; mov ah, 5 ; Alternate reset 29193 <1> ;rwdsk_fd_reset: 29194 <1> ; ;int 13h 29195 <1> ; call int13h 29196 <1> ; jnc short rwdsk_retry 29197 <1> ; mov [esi], ah ; error code ; 10/07/2015 29198 <1> ; jmp short rwdsk_ok 29199 <1> 29200 <1> ; Original UNIX v1 - drum (& disk) interrupt routine 29201 <1> ; (Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts) 29202 <1> ; 29203 <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now. 29204 <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 29205 <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h 29206 <1> ; that uses hardware -transfer has been completed- interrupt inside it. 29207 <1> ; In a next Retro UNIX 386 version, these interrupts 29208 <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine 29209 <1> ; as in original unix v1. 29210 <1> ; I am not removing IBM BIOS source code derivatives -compatible code- 29211 <1> ; for now, regarding the new/next 32 bit TRDOS project by me 29212 <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.) 29213 <1> ; 29214 <1> ; Erdogan tan (10/07/2015) 29215 <1> 29216 <1> ;drum: / interrupt handler 29217 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 29218 <1> ; jsr r0,trapt; dcs; rfap; 1 / check for stray interrupt or 29219 <1> ; / error 29220 <1> ; br 3f / no, error 29221 <1> ; br 2f / error 29222 <1> ; 29223 <1> ;disk: 29224 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 29225 <1> ; jmp *$0f 29226 <1> ;0: 29227 <1> ; jsr r0,trapt; rkcs; rkap; 2 29228 <1> ; br 3f / no, errors 29229 <1> ; mov $115,(r2) / drive reset, errbit was set 29230 <1> ; mov $1f,0b-2 / next time jmp *$0f is executed jmp will be 29231 <1> ; / to 1f 29232 <1> ; br 4f 29233 <1> ;1: 29234 <1> ; bit $20000,rkcs 29235 <1> ; beq 4f / wait for seek complete 29236 <1> ; mov $0b,0b-2 29237 <1> ; mov rkap,r1 29238 <1> ;2: 29239 <1> ; bit $3000,(r1) / are bits 9 or 10 set in the 1st word of 29240 <1> ; / the disk buffer 29241 <1> ; bne 3f / no, branch ignore error if outstanding 29242 <1> ; inc r1 29243 <1> ; asr (r1) 29244 <1> ; asr (r1) 29245 <1> ; asr (r1) / reissue request 29246 <1> ; dec r1 29247 <1> ;3: 29248 <1> ; bic $30000,(r1) / clear bits 12 and 13 in 1st word of buffer 29249 <1> ; mov ac,-(sp) 29250 <1> ; mov mq,-(sp) / put these on the stack 29251 <1> ; mov sc,-(sp) 29252 <1> ; jsr r0,poke 29253 <1> ; mov (sp)+,sc 29254 <1> ; mov (sp)+,mq / pop them off stack 29255 <1> ; mov (sp)+,ac 29256 <1> ;4: 29257 <1> ; jmp retisp / u4-3 29258 <1> ; 29259 <1> ;trapt: / r2 points to the 29260 <1> ; mov (r0)+,r2 / device control register 29261 <1> ; mov *(r0)+,r1 / transaction pointer points to buffer 29262 <1> ; tst (sp)+ 29263 <1> ; tstb (r2) / is ready bit of dcs set? 29264 <1> ; bge 4b / device still active so branch 29265 <1> ; bit (r0),active / was device busy? 29266 <1> ; beq 4b / no, stray interrupt 29267 <1> ; bic (r0)+,active / yes, set active to zero 29268 <1> ; tst (r2) / test the err(bit is) of dcs 29269 <1> ; bge 2f / if no error jump to 2f 29270 <1> ; tst (r0)+ / skip on error 29271 <1> ; 2: 29272 <1> ; jmp (r0) 29273 <1> 29274 <1> ; 27/11/2021 - Retro UNIX 386 v2 compatibility code 29275 <1> get_system_time: 29276 <1> ; 27/10/2021 29277 <1> ; 21/02/2020 - Retro UNIX 386 v2 29278 <1> ; get system time 29279 <1> ; (from recent value which is saved in RTC interrupt) 29280 <1> ; Input: 29281 <1> ; none 29282 <1> ; Return: 29283 <1> ; eax = system time in unix epoch format 29284 <1> ; 29285 <1> ; Modified registers: eax, ecx, edx 29286 <1> 29287 <1> ; 27/11/2021 29288 00005B57 53 <1> push ebx 29289 00005B58 E8DDD0FFFF <1> call epoch 29290 00005B5D 5B <1> pop ebx 29291 00005B5E C3 <1> retn 29292 <1> 29293 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 29294 <1> ; ('get_serial_number' is not used in v1.2 kernel) 29295 <1> ;get_serial_number: 29296 <1> ; temporary - 21/02/2020 29297 <1> ; 26/04/2020 (esi) 29298 <1> ; 25/04/2020 29299 <1> ; (Possible) Modified registers: eax, ecx, edx 29300 <1> ; (edi, ebx & esi registers must be preserved) 29301 <1> ; Return: 29302 <1> ; eax = 32 bit serial number 29303 <1> ; (edx = high 32 bit of 64 bit serial number) 29304 <1> ; -64 bit serial numbers will not be used in RUNIX 386 v2- 29305 <1> 29306 <1> ;retn 29307 %include 'u9.s' ; 29/06/2015 29308 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 29309 <1> ; (re-write kernel for test by using previous version without a major defect) 29310 <1> ; **************************************************************************** 29311 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.4) - SYS9.INC 29312 <1> ; Last Modification: 27/12/2022 (Previous: 08/08/2022) 29313 <1> ; ---------------------------------------------------------------------------- 29314 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 29315 <1> ; (v0.1 - Beginning: 11/07/2012) 29316 <1> ; 29317 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 29318 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 29319 <1> ; 29320 <1> ; 29321 <1> ; 29322 <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s 29323 <1> ; 29324 <1> ; **************************************************************************** 29325 <1> 29326 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 - Printer BIOS (Functions) 29327 <1> 29328 <1> getch: 29329 <1> ; 30/06/2015 29330 <1> ; 18/02/2015 - Retro UNIX 386 v1 - feature only! 29331 00005B5F 28C0 <1> sub al, al ; 0 29332 <1> getch_q: ; 06/08/2015 29333 00005B61 8A25[96670000] <1> mov ah, [ptty] ; active (current) video page 29334 00005B67 EB06 <1> jmp short getc_n 29335 <1> 29336 <1> getc: 29337 <1> ; 12/11/2015 29338 <1> ; 15/09/2015 29339 <1> ; 01/07/2015 29340 <1> ; 30/06/2015 29341 <1> ; 18/02/2015 (Retro UNIX 386 v1 - Beginning) 29342 <1> ; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1) 29343 <1> ; 29344 <1> ; Retro UNIX 8086 v1 modification ! 29345 <1> ; 29346 <1> ; 'getc' gets (next) character 29347 <1> ; from requested TTY (keyboard) buffer 29348 <1> ; INPUTS -> 29349 <1> ; [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2) 29350 <1> ; AL=0 -> Get (next) character from requested TTY buffer 29351 <1> ; (Keyboard buffer will point to 29352 <1> ; next character at next call) 29353 <1> ; AL=1 -> Test a key is available in requested TTY buffer 29354 <1> ; (Keyboard buffer will point to 29355 <1> ; current character at next call) 29356 <1> ; OUTPUTS -> 29357 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 29358 <1> ; ZF=0 -> AX has (current) character 29359 <1> ; AL = ascii code 29360 <1> ; AH = scan code (AH = line status for COM1 or COM2) 29361 <1> ; (cf=1 -> error code/flags in AH) 29362 <1> ; Original UNIX V1 'getc': 29363 <1> ; get a character off character list 29364 <1> ; 29365 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 29366 <1> ; 29367 <1> ; 30/06/2015 (32 bit modifications) 29368 <1> ; 16/07/2013 29369 <1> ; mov [getctty], ah 29370 <1> ; 29371 <1> 29372 00005B69 8A25[D96C0000] <1> mov ah, [u.ttyn] ; 28/07/2013 29373 <1> getc_n: 29374 <1> ; 30/06/2015 29375 00005B6F 08E4 <1> or ah, ah 29376 00005B71 740D <1> jz short getc0 29377 00005B73 D0E4 <1> shl ah, 1 29378 00005B75 0FB6DC <1> movzx ebx, ah 29379 00005B78 81C3[98670000] <1> add ebx, ttychr 29380 00005B7E EB05 <1> jmp short getc1 29381 <1> getc0: 29382 00005B80 BB[98670000] <1> mov ebx, ttychr 29383 <1> getc1: 29384 00005B85 668B0B <1> mov cx, [ebx] ; ascii & scan code 29385 <1> ; (by kb_int) 29386 00005B88 6609C9 <1> or cx, cx 29387 00005B8B 7507 <1> jnz short getc2 29388 00005B8D 20C0 <1> and al, al 29389 00005B8F 7415 <1> jz short getc_s 29390 <1> ;xor ax, ax 29391 <1> ; 30/11/2021 29392 00005B91 31C0 <1> xor eax, eax 29393 00005B93 C3 <1> retn 29394 <1> getc2: 29395 00005B94 20C0 <1> and al, al 29396 00005B96 6689C8 <1> mov ax, cx 29397 00005B99 66B90000 <1> mov cx, 0 29398 00005B9D 7506 <1> jnz short getc3 29399 <1> getc_sn: 29400 00005B9F 66890B <1> mov [ebx], cx ; 0, reset 29401 00005BA2 6639C8 <1> cmp ax, cx ; zf = 0 29402 <1> getc3: 29403 00005BA5 C3 <1> retn 29404 <1> getc_s: 29405 <1> ; 12/11/2015 29406 <1> ; 15/09/2015 29407 <1> ; 01/07/2015 29408 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 29409 <1> ; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1) 29410 <1> ; 29411 <1> ; tty of the current process is not 29412 <1> ; current tty (ptty); so, current process only 29413 <1> ; can use keyboard input when its tty becomes 29414 <1> ; current tty (ptty). 29415 <1> ; 'sleep' is for preventing an endless lock 29416 <1> ; during this tty input request. 29417 <1> ; (Because, the user is not looking at the video page 29418 <1> ; of the process to undersand there is a keyboard 29419 <1> ; input request.) 29420 <1> ; 29421 <1> ;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 29422 <1> ; 29423 <1> ; 05/10/2013 29424 <1> ; ah = byte ptr [u.ttyn] ; (tty number) 29425 <1> ; 29426 <1> ; 10/10/2013 29427 <1> gcw0: 29428 00005BA6 B10A <1> mov cl, 10 ; ch = 0 29429 <1> gcw1: 29430 <1> ; 12/11/2015 29431 00005BA8 E8C5D6FFFF <1> call intract ; jumps to 'sysexit' if [u.quit] = FFFFh 29432 <1> ; 10/10/2013 29433 00005BAD E841EBFFFF <1> call idle 29434 00005BB2 668B03 <1> mov ax, [ebx] ; ascii & scan code 29435 <1> ; (by kb_int) 29436 00005BB5 6609C0 <1> or ax, ax 29437 <1> ; jnz short gcw3 29438 00005BB8 7519 <1> jnz short gcw2 ; 15/09/2015 29439 <1> ; 30/06/2015 29440 00005BBA FEC9 <1> dec cl 29441 00005BBC 75EA <1> jnz short gcw1 29442 <1> ; 29443 00005BBE 8A25[D96C0000] <1> mov ah, [u.ttyn] ; 20/10/2013 29444 <1> ; ; 10/12/2013 29445 <1> ; cmp ah, [ptty] 29446 <1> ; jne short gcw2 29447 <1> ; ; 14/02/2014 29448 <1> ; cmp byte [u.uno], 1 29449 <1> ; jna short gcw0 29450 <1> ;gcw2: 29451 00005BC4 E8B7EBFFFF <1> call sleep 29452 <1> ; 29453 <1> ; 20/09/2013 29454 00005BC9 8A25[D96C0000] <1> mov ah, [u.ttyn] 29455 00005BCF 30C0 <1> xor al, al 29456 00005BD1 EB9C <1> jmp short getc_n 29457 <1> ;gcw3: 29458 <1> gcw2: ; 15/09/2015 29459 <1> ; 10/10/2013 29460 00005BD3 30C9 <1> xor cl, cl 29461 00005BD5 EBC8 <1> jmp short getc_sn 29462 <1> 29463 <1> putc: 29464 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 29465 <1> ; 13/08/2015 29466 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 29467 <1> ; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1) 29468 <1> ; 29469 <1> ; Retro UNIX 8086 v1 modification ! 29470 <1> ; 29471 <1> ; 'putc' puts a character 29472 <1> ; onto requested (tty) video page or 29473 <1> ; serial port 29474 <1> ; INPUTS -> 29475 <1> ; AL = ascii code of the character 29476 <1> ; AH = video page (tty) number (0 to 7) 29477 <1> ; (8 is COM1, 9 is COM2) 29478 <1> ; OUTPUTS -> 29479 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 29480 <1> ; ZF=0 -> AX has (current) character 29481 <1> ; cf=0 and AH = 0 -> no error 29482 <1> ; cf=1 and AH > 0 -> error (only for COM1 and COM2) 29483 <1> ; 29484 <1> ; Original UNIX V1 'putc': 29485 <1> ; put a character at the end of character list 29486 <1> ; 29487 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 29488 <1> ; 29489 00005BD7 80FC07 <1> cmp ah, 7 29490 00005BDA 770A <1> ja short sndc ; 05/12/2021 29491 <1> ; 30/06/2015 29492 00005BDC 0FB6DC <1> movzx ebx, ah 29493 <1> ; 13/08/2015 29494 00005BDF B407 <1> mov ah, 07h ; black background, light gray character color 29495 00005BE1 E9CEB6FFFF <1> jmp write_tty ; 'video.inc' 29496 <1> 29497 <1> sndc: ; 29498 <1> ; 29499 <1> ; 12/01/2022 29500 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 29501 <1> ; 17/11/2015 29502 <1> ; 16/11/2015 29503 <1> ; 11/11/2015 29504 <1> ; 10/11/2015 29505 <1> ; 09/11/2015 29506 <1> ; 08/11/2015 29507 <1> ; 07/11/2015 29508 <1> ; 06/11/2015 (serial4.asm, 'sendchr') 29509 <1> ; 29/10/2015 29510 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 29511 <1> ; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1) 29512 <1> ; 29513 <1> ; Retro UNIX 8086 v1 feature only ! 29514 <1> ; 29515 <1> ; ah = [u.ttyn] 29516 <1> ; 29517 <1> ; 30/06/2015 29518 00005BE6 80EC08 <1> sub ah, 8 ; ; 0 = tty8 or 1 = tty9 29519 <1> ; 07/11/2015 29520 00005BE9 0FB6DC <1> movzx ebx, ah ; serial port index (0 or 1) 29521 <1> sndc0: 29522 <1> ; 07/11/2015 29523 00005BEC E8DDEBFFFF <1> call isintr ; quit (ctrl+break) check 29524 00005BF1 7405 <1> jz short sndc1 29525 00005BF3 E87AD6FFFF <1> call intract ; quit (ctrl+break) check 29526 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 29527 <1> sndc1: 29528 <1> ; 16/11/2015 29529 <1> ;mov cx, ax ; *** al = character (to be sent) 29530 <1> ; 24/12/2021 29531 00005BF8 89C1 <1> mov ecx, eax ; *** al = character (to be sent) 29532 <1> sndcx: 29533 00005BFA 8A83[DA670000] <1> mov al, [ebx+schar] ; last sent character 29534 00005C00 8AA3[D8670000] <1> mov ah, [ebx+rchar] ; last received character 29535 <1> ; 29536 <1> ; 17/11/2015 29537 <1> ; check 'request for response' status 29538 00005C06 80BB[D4670000]00 <1> cmp byte [ebx+req_resp], 0 29539 00005C0D 740A <1> jz short query 29540 <1> response: 29541 00005C0F FE05[D7670000] <1> inc byte [comqr] ; query or response status 29542 00005C15 B0FF <1> mov al, 0FFh 29543 00005C17 EB14 <1> jmp short sndc3 29544 <1> query: 29545 00005C19 08C0 <1> or al, al ; 0 = query (also end of text) 29546 00005C1B 750E <1> jnz short sndc2 ; normal character 29547 <1> ;cmp ah, 0FFh ; is it responded by terminal ? 29548 <1> ;je short sndc2 ; yes, already responded 29549 <1> ; 16/11/2015 29550 <1> ; query: request for response (again) 29551 00005C1D 8883[D8670000] <1> mov [ebx+rchar], al ; 0 ; reset 29552 00005C23 FE05[D7670000] <1> inc byte [comqr] ; query or response status 29553 00005C29 EB02 <1> jmp short sndc3 29554 <1> sndc2: 29555 00005C2B 88C8 <1> mov al, cl ; *** character (to be sent) 29556 <1> sndc3: 29557 00005C2D 8883[DA670000] <1> mov [ebx+schar], al ; current character (to be sent) 29558 00005C33 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 29559 <1> ; 30/06/2015 29560 00005C35 E865CFFFFF <1> call sp_status ; get serial port status 29561 <1> ; AL = Line status, AH = Modem status 29562 <1> ; 07/11/2015 29563 00005C3A A880 <1> test al, 80h 29564 00005C3C 7504 <1> jnz short sndc4 29565 00005C3E A820 <1> test al, 20h ; Transmitter holding register empty ? 29566 00005C40 751A <1> jnz short sndc5 29567 <1> sndc4: ; Check line status again 29568 <1> ; 16/11/2015 29569 <1> ;push cx 29570 <1> ; 24/12/2021 29571 00005C42 51 <1> push ecx 29572 <1> ;mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 29573 <1> ; 12/01/2022 29574 00005C43 31C9 <1> xor ecx, ecx 29575 00005C45 B106 <1> mov cl, 6 29576 00005C47 E85FB7FFFF <1> call WAITF 29577 <1> ;pop cx 29578 <1> ; 24/12/1021 29579 00005C4C 59 <1> pop ecx 29580 <1> ; 29581 00005C4D 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 29582 00005C4F E84BCFFFFF <1> call sp_status ; get serial port status 29583 <1> ; 16/11/2015 29584 <1> ; 09/11/2015 29585 <1> ; 08/11/2015 29586 00005C54 A880 <1> test al, 80h ; time out error 29587 00005C56 7565 <1> jnz short sndc7 29588 00005C58 A820 <1> test al, 20h ; Transmitter holding register empty ? 29589 00005C5A 7461 <1> jz short sndc7 29590 <1> sndc5: 29591 00005C5C 8A83[DA670000] <1> mov al, [ebx+schar] ; character (to be sent) 29592 00005C62 66BAF803 <1> mov dx, 3F8h ; data port (COM2) 29593 00005C66 28DE <1> sub dh, bl 29594 00005C68 EE <1> out dx, al ; send on serial port 29595 <1> ; 10/11/2015 29596 <1> ; delay for 3*30 (3*(15..80)) micro seconds 29597 <1> ; (to improve text flow to the terminal) 29598 <1> ; ('diskette.inc': 'WAITF') 29599 <1> ; Uses port 61h, bit 4 to have CPU speed independent waiting. 29600 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 29601 <1> ;push cx 29602 <1> ; 24/12/2021 29603 00005C69 51 <1> push ecx 29604 <1> ;mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 29605 <1> ; 12/01/2022 29606 00005C6A 29C9 <1> sub ecx, ecx 29607 00005C6C B106 <1> mov cl, 6 29608 00005C6E E838B7FFFF <1> call WAITF 29609 <1> ;pop cx 29610 <1> ; 24/12/1021 29611 00005C73 59 <1> pop ecx 29612 <1> ; 29613 <1> ; 07/11/2015 29614 00005C74 88D8 <1> mov al, bl ; al = 0 (tty8) or 1 (tty9) 29615 <1> ; 29616 00005C76 E824CFFFFF <1> call sp_status ; get serial port status 29617 <1> ; AL = Line status, AH = Modem status 29618 <1> ; 29619 00005C7B E84EEBFFFF <1> call isintr ; quit (ctrl+break) check 29620 00005C80 7405 <1> jz short sndc6 29621 00005C82 E8EBD5FFFF <1> call intract ; quit (ctrl+break) check 29622 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 29623 <1> sndc6: 29624 00005C87 3C80 <1> cmp al, 80h 29625 00005C89 7332 <1> jnb short sndc7 29626 <1> ; 29627 00005C8B 803D[D7670000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 29628 00005C92 7244 <1> jb short sndc8 ; no, normal character 29629 00005C94 883D[D7670000] <1> mov byte [comqr], bh ; 0 ; reset 29630 <1> ; 17/11/2015 29631 00005C9A E854EAFFFF <1> call idle 29632 <1> ; 29633 00005C9F 38BB[DA670000] <1> cmp [ebx+schar], bh ; 0 ; query ? 29634 <1> ;ja sndc2 ; response (will be followed by 29635 <1> ; a normal character) 29636 <1> ; 24/12/2021 29637 00005CA5 7602 <1> jna short sndc_10 29638 00005CA7 EB82 <1> jmp sndc2 29639 <1> sndc_10: 29640 <1> ; Query request must be responded by the terminal 29641 <1> ; before sending a normal character ! 29642 00005CA9 53 <1> push ebx 29643 <1> ;push cx ; *** cl = character (to be sent) 29644 <1> ; 24/12/2021 29645 00005CAA 51 <1> push ecx ; *** cl = character (to be sent) 29646 00005CAB 8A25[D96C0000] <1> mov ah, [u.ttyn] 29647 00005CB1 E8CAEAFFFF <1> call sleep ; this process will be awakened by 29648 <1> ; received data available interrupt 29649 <1> ;pop cx ; *** cl = character (to be sent) 29650 <1> ; 24/12/2021 29651 00005CB6 59 <1> pop ecx ; *** cl = character (to be sent) 29652 00005CB7 5B <1> pop ebx 29653 00005CB8 E93DFFFFFF <1> jmp sndcx 29654 <1> sndc7: 29655 <1> ; 16/11/2015 29656 00005CBD 803D[D7670000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 29657 00005CC4 7213 <1> jb short sndc9 ; no 29658 <1> ; 29659 00005CC6 88BB[D8670000] <1> mov [ebx+rchar], bh ; 0 ; reset 29660 00005CCC 88BB[DA670000] <1> mov [ebx+schar], bh ; 0 ; reset 29661 <1> ; 29662 00005CD2 883D[D7670000] <1> mov byte [comqr], bh ; 0 ; reset 29663 <1> sndc8: 29664 00005CD8 F5 <1> cmc ; jnc -> jc, jb -> jnb 29665 <1> sndc9: 29666 <1> ; AL = Line status, AH = Modem status 29667 00005CD9 C3 <1> retn 29668 <1> 29669 <1> get_cpos: 29670 <1> ; 29/06/2015 (Retro UNIX 386 v1) 29671 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 29672 <1> ; 29673 <1> ; INPUT -> bl = video page number 29674 <1> ; RETURN -> dx = cursor position 29675 <1> 29676 00005CDA 53 <1> push ebx 29677 00005CDB 83E30F <1> and ebx, 0Fh ; 07h ; tty0 to tty7 29678 00005CDE D0E3 <1> shl bl, 1 29679 00005CE0 81C3[86670000] <1> add ebx, cursor_posn 29680 00005CE6 668B13 <1> mov dx, [ebx] 29681 00005CE9 5B <1> pop ebx 29682 00005CEA C3 <1> retn 29683 <1> 29684 <1> read_ac_current: 29685 <1> ; 29/06/2015 (Retro UNIX 386 v1) 29686 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 29687 <1> ; 29688 <1> ; INPUT -> bl = video page number 29689 <1> ; RETURN -> ax = character (al) and attribute (ah) 29690 <1> 29691 00005CEB E82AB7FFFF <1> call find_position ; 'video.inc' 29692 <1> ; dx = status port 29693 <1> ; esi = cursor location/address 29694 00005CF0 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 29695 00005CF6 668B06 <1> mov ax, [esi] ; get the character and attribute 29696 00005CF9 C3 <1> retn 29697 <1> 29698 <1> syssleep: 29699 <1> ; 29/06/2015 - (Retro UNIX 386 v1) 29700 <1> ; 11/06/2014 - (Retro UNIX 8086 v1) 29701 <1> ; 29702 <1> ; Retro UNIX 8086 v1 feature only 29703 <1> ; (INPUT -> none) 29704 <1> ; 29705 00005CFA 0FB61D[F56C0000] <1> movzx ebx, byte [u.uno] ; process number 29706 00005D01 8AA3[A3680000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 29707 00005D07 E874EAFFFF <1> call sleep 29708 00005D0C E974D4FFFF <1> jmp sysret 29709 <1> 29710 <1> vp_clr: 29711 <1> ; Reset/Clear Video Page 29712 <1> ; 29713 <1> ; 05/12/2021 - (Retro UNIX 386 v1.2) 29714 <1> ; 30/06/2015 - (Retro UNIX 386 v1) 29715 <1> ; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM) 29716 <1> ; 29717 <1> ; Retro UNIX 8086 v1 feature only ! 29718 <1> ; 29719 <1> ; INPUTS -> 29720 <1> ; BL = video page number 29721 <1> ; 29722 <1> ; OUTPUT -> 29723 <1> ; none 29724 <1> ; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI)) 29725 <1> ; 29726 <1> ; 04/12/2013 29727 00005D11 28C0 <1> sub al, al 29728 <1> ; al = 0 (clear video page) 29729 <1> ; bl = video page 29730 00005D13 B407 <1> mov ah, 07h 29731 <1> ; ah = 7 (attribute/color) 29732 <1> ;xor cx, cx ; 0, left upper column (cl) & row (cl) 29733 <1> ; 05/12/2021 29734 00005D15 31C9 <1> xor ecx, ecx 29735 00005D17 66BA4F18 <1> mov dx, 184Fh ; right lower column & row (dl=24, dh=79) 29736 00005D1B E824B7FFFF <1> call scroll_up 29737 <1> ; bl = video page 29738 <1> ;xor dx, dx ; 0 (cursor position) 29739 <1> ; 05/12/2021 29740 00005D20 31D2 <1> xor edx, edx 29741 00005D22 E997B6FFFF <1> jmp set_cpos 29742 <1> 29743 <1> sysmsg: 29744 <1> ; 11/12/2021 29745 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 29746 <1> ; 11/11/2015 29747 <1> ; 01/07/2015 - (Retro UNIX 386 v1 feature only!) 29748 <1> ; Print user-application message on user's console tty 29749 <1> ; 29750 <1> ; Input -> EBX = Message address 29751 <1> ; ECX = Message length (max. 255) 29752 <1> ; DL = Color (IBM PC Rombios color attributes) 29753 <1> ; 29754 00005D27 81F9FF000000 <1> cmp ecx, MAX_MSG_LEN ; 255 29755 <1> ;ja sysret ; nothing to do with big message size 29756 00005D2D 7779 <1> ja short sysmsg8 ; 11/12/2021 29757 00005D2F 08C9 <1> or cl, cl 29758 <1> ;jz sysret 29759 00005D31 7475 <1> jz short sysmsg8 ; 11/12/2021 29760 00005D33 20D2 <1> and dl, dl 29761 00005D35 7502 <1> jnz short sysmsg0 29762 00005D37 B207 <1> mov dl, 07h ; default color 29763 <1> ; (black background, light gray character) 29764 <1> sysmsg0: 29765 00005D39 891D[C86C0000] <1> mov [u.base], ebx 29766 00005D3F 8815[97670000] <1> mov [ccolor], dl ; color attributes 29767 00005D45 89E5 <1> mov ebp, esp 29768 00005D47 31DB <1> xor ebx, ebx ; 0 29769 00005D49 891D[D06C0000] <1> mov [u.nread], ebx ; 0 29770 <1> ; 29771 00005D4F 381D[166D0000] <1> cmp [u.kcall], bl ; 0 29772 00005D55 7772 <1> ja short sysmsgk ; Temporary (01/07/2015) 29773 <1> ; 29774 00005D57 890D[CC6C0000] <1> mov [u.count], ecx 29775 00005D5D 41 <1> inc ecx ; + 00h ; ASCIIZ ; 04/12/2021 29776 <1> ; 04/12/2021 29777 <1> ; (dword alignment for esp) 29778 00005D5E F6C103 <1> test cl, 3 29779 00005D61 7404 <1> jz short sysmsg_7 29780 00005D63 80C903 <1> or cl, 3 29781 00005D66 41 <1> inc ecx 29782 <1> sysmsg_7: 29783 00005D67 29CC <1> sub esp, ecx 29784 00005D69 89E7 <1> mov edi, esp 29785 00005D6B 89E6 <1> mov esi, esp 29786 00005D6D 66891D[106D0000] <1> mov [u.pcount], bx ; reset page (phy. addr.) counter 29787 <1> ; 11/11/2015 29788 00005D74 8A25[DA6C0000] <1> mov ah, [u.ttyp] ; recent open tty 29789 <1> ; 0 = none 29790 00005D7A FECC <1> dec ah 29791 00005D7C 790C <1> jns short sysmsg1 29792 00005D7E 8A1D[F56C0000] <1> mov bl, [u.uno] ; process number 29793 00005D84 8AA3[A3680000] <1> mov ah, [ebx+p.ttyc-1] ; user's (process's) console tty 29794 <1> sysmsg1: 29795 00005D8A 8825[D96C0000] <1> mov [u.ttyn], ah 29796 <1> sysmsg2: 29797 00005D90 E898F5FFFF <1> call cpass 29798 00005D95 7416 <1> jz short sysmsg5 29799 00005D97 AA <1> stosb 29800 00005D98 20C0 <1> and al, al 29801 00005D9A 75F4 <1> jnz short sysmsg2 29802 <1> sysmsg3: 29803 00005D9C 80FC07 <1> cmp ah, 7 ; tty number 29804 00005D9F 7711 <1> ja short sysmsg6 ; serial port 29805 00005DA1 E83E000000 <1> call print_cmsg 29806 <1> sysmsg4: 29807 00005DA6 89EC <1> mov esp, ebp 29808 <1> sysmsg8: ; 11/12/2021 29809 00005DA8 E9D8D3FFFF <1> jmp sysret 29810 <1> sysmsg5: 29811 00005DAD C60700 <1> mov byte [edi], 0 29812 00005DB0 EBEA <1> jmp short sysmsg3 29813 <1> sysmsg6: 29814 00005DB2 8A06 <1> mov al, [esi] 29815 00005DB4 E82DFEFFFF <1> call sndc 29816 00005DB9 72EB <1> jc short sysmsg4 29817 00005DBB 803E00 <1> cmp byte [esi], 0 ; 0 is stop character 29818 00005DBE 76E6 <1> jna short sysmsg4 29819 00005DC0 46 <1> inc esi 29820 00005DC1 8A25[D96C0000] <1> mov ah, [u.ttyn] 29821 00005DC7 EBE9 <1> jmp short sysmsg6 29822 <1> 29823 <1> sysmsgk: ; Temporary (01/07/2015) 29824 <1> ; The message has been sent by Kernel (ASCIIZ string) 29825 <1> ; (ECX -character count- will not be considered) 29826 00005DC9 8B35[C86C0000] <1> mov esi, [u.base] 29827 00005DCF 8A25[96670000] <1> mov ah, [ptty] ; present/current screen (video page) 29828 00005DD5 8825[D96C0000] <1> mov [u.ttyn], ah 29829 00005DDB C605[166D0000]00 <1> mov byte [u.kcall], 0 29830 00005DE2 EBB8 <1> jmp short sysmsg3 29831 <1> 29832 <1> print_cmsg: 29833 <1> ; 01/07/2015 (retro UNIX 386 v1 feature only !) 29834 <1> ; 29835 <1> ; print message (on user's console tty) 29836 <1> ; with requested color 29837 <1> ; 29838 <1> ; INPUTS: 29839 <1> ; esi = message address 29840 <1> ; [u.ttyn] = tty number (0 to 7) 29841 <1> ; [ccolor] = color attributes (IBM PC BIOS colors) 29842 <1> ; 29843 00005DE4 AC <1> lodsb 29844 <1> pcmsg1: 29845 00005DE5 56 <1> push esi 29846 00005DE6 0FB61D[D96C0000] <1> movzx ebx, byte [u.ttyn] 29847 00005DED 8A25[97670000] <1> mov ah, [ccolor] 29848 00005DF3 E8BCB4FFFF <1> call write_tty 29849 00005DF8 5E <1> pop esi 29850 00005DF9 AC <1> lodsb 29851 00005DFA 20C0 <1> and al, al ; 0 29852 00005DFC 75E7 <1> jnz short pcmsg1 29853 00005DFE C3 <1> retn 29854 <1> 29855 <1> sysgeterr: 29856 <1> ; 16/02/2022 - Retro UNIX 386 v1.2 29857 <1> ; 09/12/2015 29858 <1> ; 21/09/2015 - (Retro UNIX 386 v1 feature only!) 29859 <1> ; Get last error number or page fault count 29860 <1> ; (for debugging) 29861 <1> ; 29862 <1> ; Input -> EBX = return type 29863 <1> ; 0 = last error code (which is in 'u.error') 29864 <1> ; FFFFFFFFh = page fault count for running process 29865 <1> ; FFFFFFFEh = total page fault count 29866 <1> ; 1 .. FFFFFFFDh = undefined 29867 <1> ; 29868 <1> ; Output -> EAX = last error number or page fault count 29869 <1> ; (depending on EBX input) 29870 <1> ; 29871 00005DFF 21DB <1> and ebx, ebx 29872 00005E01 750F <1> jnz short glerr_2 29873 <1> glerr_0: 29874 00005E03 A1[186D0000] <1> mov eax, [u.error] 29875 <1> glerr_1: 29876 <1> getmem_ret: ; 27/12/2022 29877 00005E08 A3[A46C0000] <1> mov [u.r0], eax 29878 <1> ;retn 29879 <1> ; 16/02/2022 (BugFix) 29880 00005E0D E973D3FFFF <1> jmp sysret 29881 <1> glerr_2: 29882 00005E12 43 <1> inc ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh 29883 00005E13 74FD <1> jz short glerr_2 ; page fault count for process 29884 00005E15 43 <1> inc ebx ; FFFFFFFFh -> 0 29885 00005E16 75EB <1> jnz short glerr_0 29886 00005E18 A1[1C680000] <1> mov eax, [PF_Count] ; total page fault count 29887 00005E1D EBE9 <1> jmp short glerr_1 29888 <1> glerr_3: 29889 00005E1F A1[1C6D0000] <1> mov eax, [u.pfcount] 29890 00005E24 EBE2 <1> jmp short glerr_1 29891 <1> 29892 <1> sysmemory: 29893 <1> ; 27/12/2022 - Retro UNIX 386 v1.2 feature only! 29894 <1> ; Get available (total or free) memory in pages 29895 <1> ; 29896 <1> ; Input -> EBX = return type 29897 <1> ; 0 = return total memory in pages (in eax) 29898 <1> ; 1 = return free memory in pages (in eax) 29899 <1> ; >1 is invalid 29900 <1> ; 29901 <1> ; Output -> EAX = available memory in pages (4096 bytes) 29902 <1> ; (depending on EBX input) 29903 <1> ; 29904 00005E26 4B <1> dec ebx 29905 00005E27 780E <1> js short get_total_memory ; ebx = 0 -> -1 29906 00005E29 7413 <1> jz short get_free_memory ; ebx = 1 -> 0 29907 <1> 29908 <1> ; invalid_memory_option (ebx input value > 1) 29909 00005E2B B001 <1> mov al, 1 29910 <1> ; eax = ERR_INV_FUNC ; = 1 29911 <1> ; 'invalid system call (or function) !' 29912 00005E2D A3[186D0000] <1> mov [u.error], eax 29913 00005E32 E92ED3FFFF <1> jmp error 29914 <1> 29915 <1> get_total_memory: 29916 00005E37 A1[6C670000] <1> mov eax, [memory_size] 29917 <1> ;getmem_ret: 29918 <1> ;mov [u.r0], eax 29919 <1> ;jmp sysret 29920 00005E3C EBCA <1> jmp short getmem_ret 29921 <1> 29922 <1> get_free_memory: 29923 <1> ; (! debugging !) 29924 00005E3E E8DAB7FFFF <1> call calc_free_mem ; re-calculate free memory (without setting) 29925 <1> ; edx = calculated free pages 29926 00005E43 A1[70670000] <1> mov eax, [free_pages] ; compare with the system's set value 29927 00005E48 39D0 <1> cmp eax, edx 29928 00005E4A 74BC <1> je short getmem_ret ; they are same, good ! 29929 <1> ; something has gone wrong !? 29930 <1> ; reset free pages and first free page search start value 29931 00005E4C 8915[70670000] <1> mov [free_pages], edx ; memory allocation procedure uses this 29932 00005E52 8B15[7C670000] <1> mov edx, [first_page] ; start (initial) value for mem allocation 29933 <1> ; (the 1st available page -init- for user) 29934 00005E58 8915[74670000] <1> mov [next_page], edx ; 1st free memory page search proc uses this 29935 00005E5E EBA8 <1> jmp short getmem_ret 29936 <1> 29937 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 - PRINTER BIOS (Functions) 29938 <1> 29939 <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 29940 <1> ; 29941 <1> ;--- INT 17 H ------------------------------------------------------------------ 29942 <1> ; PRINTER_IO : 29943 <1> ; THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER : 29944 <1> ; INPUT : 29945 <1> ; (AH)= 00H PRINT THE CHARACTER IN (AL) : 29946 <1> ; ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT) : 29947 <1> ; OTHER BITS SET AS ON NORMAL STATUS CALL : 29948 <1> ; (AH)= 01H INITIALIZE THE PRINTER PORT : 29949 <1> ; RETURNS WITH (AH) SET WITH PRINTER STATUS : 29950 <1> ; (AH)= 02H READ THE PRINTER STATUS INTO (AH) : 29951 <1> ; 7 6 5 4 3 2-1 0 : 29952 <1> ; | | | | | | |_TIME OUT : 29953 <1> ; | | | | | | : 29954 <1> ; | | | | | |_ UNUSED : 29955 <1> ; | | | | | : 29956 <1> ; | | | | |_ 1 = I/O ERROR : 29957 <1> ; | | | | : 29958 <1> ; | | | |_ 1 = SELECTED : 29959 <1> ; | | | : 29960 <1> ; | | |_ 1 = OUT OF PAPER : 29961 <1> ; | | : 29962 <1> ; | |_ 1 = ACKNOWLEDGE : 29963 <1> ; | : 29964 <1> ; |_ 1 = NOT BUSY : 29965 <1> ; : 29966 <1> ; (DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES : 29967 <1> ; IN @PRINTER_BASE AREA : 29968 <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S) : 29969 <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS) : 29970 <1> ; : 29971 <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT : 29972 <1> ; TIME OUT WAITS. DEFAULT=20 * 4 : 29973 <1> ; : 29974 <1> ; REGISTERS (AH) IS MODIFIED WITH STATUS INFORMATION : 29975 <1> ; ALL OTHERS UNCHANGED : 29976 <1> ;------------------------------------------------------------------------------- 29977 <1> 29978 <1> int17h: 29979 <1> ; 12/06/2022 - Retro UNIX 386 v1.2 29980 <1> ; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985) 29981 <1> ; 29982 <1> ; (Default printer port: 378h) ; LPT1 29983 <1> ; (Number of printers = 1) 29984 <1> 29985 <1> PRINTER_BASE equ 378h ; LPT1 29986 <1> ;PRINT_TIM_OUT equ 4*80*65536 29987 <1> ; (Ref: IBM PC-AT BIOS v2 PRT.ASM) 29988 <1> 29989 <1> PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY 29990 <1> ; (Ref: AWARD BIOS 1999 ATORGS.ASM) 29991 <1> 29992 <1> ; INPUT: 29993 <1> ; ah = 0 -> print the character in AL 29994 <1> ; (sys write with write count >0) 29995 <1> ; ah = 1 -> initialize printer port 29996 <1> ; (sys open) 29997 <1> ; ah = 2 -> read the printer status 29998 <1> ; (sys write with write count = 0) 29999 <1> ; OUTPUT: 30000 <1> ; ah = printer status 30001 <1> 30002 <1> ; Modified registers: eax, ecx, edx 30003 <1> 30004 <1> PRINTER_IO_1: 30005 00005E60 08E4 <1> or ah, ah 30006 00005E62 7417 <1> jz short _b20 30007 00005E64 FECC <1> dec ah 30008 00005E66 7444 <1> jz short _b80 30009 <1> ;dec ah 30010 <1> ;jz short _b50 30011 <1> _b50: 30012 <1> ;----- PRINTER STATUS 30013 <1> B50: 30014 00005E68 50 <1> push eax ; SAVE (AL) REGISTER 30015 <1> B60: 30016 00005E69 66BA7903 <1> mov dx, PRINTER_BASE+1 30017 <1> ; GET PRINTER ATTACHMENT BASE ADDRESS 30018 <1> ; POINT TO CONTROL PORT 30019 00005E6D EC <1> in al, dx ; PRE-CHARGE +BUSY LINE IF FLOATING 30020 00005E6E EC <1> in al, dx ; GET PRINTER STATUS HARDWARE BITS 30021 00005E6F 88C4 <1> mov ah, al ; SAVE 30022 00005E71 80E4F8 <1> and ah, 0F8h ; TURN OFF UNUSED BITS 30023 <1> B70: 30024 00005E74 5A <1> pop edx ; RECOVER (AL) REGISTER 30025 00005E75 88D0 <1> mov al, dl ; MOVE CHARACTER INTO (AL) 30026 00005E77 80F448 <1> xor ah, 48h ; FLIP A COUPLE OF BITS 30027 <1> B10: 30028 00005E7A C3 <1> retn ; RETURN FROM ROUTINE WITH STATUS IN AH 30029 <1> _b20: 30030 <1> ;----- PRINT THE CHARACTER IN (AL) 30031 00005E7B B9A08C0000 <1> mov ecx, PRINT_TIM_OUT ; (1 second) 30032 <1> B20: 30033 00005E80 50 <1> push eax ; SAVE VALUE TO PRINT 30034 00005E81 66BA7803 <1> mov dx, PRINTER_BASE 30035 00005E85 EE <1> out dx, al ; OUTPUT CHARACTER TO DATA PORT 30036 00005E86 FEC2 <1> inc dl ; POINT TO STATUS PORT 30037 <1> 30038 <1> ;----- CHECK FOR PRINTER BUSY 30039 <1> B25: 30040 <1> ;----- WAIT BUSY 30041 <1> B35: 30042 00005E88 EC <1> in al, dx ; GET STATUS 30043 00005E89 88C4 <1> mov ah, al ; STATUS TO (AH) ALSO 30044 00005E8B A880 <1> test al, 80h ; IS THE PRINTER CURRENTLY BUSY? (*) 30045 00005E8D 750F <1> jnz short B40 ; GO TO OUTPUT STROBE 30046 00005E8F E831000000 <1> call WAIT_REFRESH ; (wait for 30 micro seconds) 30047 00005E94 E2F2 <1> loop B35 ; LOOP IF YES (*) 30048 <1> 30049 00005E96 80CC01 <1> or ah, 1 ; SET ERROR FLAG 30050 00005E99 80E4F9 <1> and ah, 0F9h ; TURN OFF THE UNUSED BITS 30051 00005E9C EBD6 <1> jmp short B70 ; RETURN WITH ERROR FLAG SET 30052 <1> 30053 <1> B40: ; SEND STROBE PULSE 30054 00005E9E B00D <1> mov al, 0Dh ; SET THE STROBE LOW (BIT ON) 30055 00005EA0 6642 <1> inc dx ; OUTPUT STROBE TO CONTROL PORT 30056 00005EA2 FA <1> cli ; PREVENT INTERRUPT PULSE STRETCHING 30057 00005EA3 EE <1> out dx, al ; OUTPUT STROBE BIT > 1us < 5us 30058 <1> ; IODELAY 30059 <1> ;jmp short $+2 ; I/O DELAY TO ALLOW FOR LINE LOADING 30060 <1> ;jmp short $+2 ; AND FOR CORRECT PULSE WIDTH 30061 <1> ; NEWIODELAY 30062 00005EA4 E6EB <1> out 0EBh, al 30063 <1> 30064 00005EA6 B00C <1> mov al, 0Ch ; SET THE -STROBE HIGH 30065 00005EA8 EE <1> out dx, al 30066 00005EA9 FB <1> sti ; INTERRUPTS BACK ON 30067 <1> ;pop eax ; RECOVER THE OUTPUT CHAR 30068 <1> ;jmp short B50 30069 00005EAA EBBD <1> jmp short B60 30070 <1> 30071 <1> _b80: 30072 <1> ;----- INITIALIZE THE PRINTER PORT 30073 <1> B80: 30074 00005EAC 50 <1> push eax ; SAVE (AL) 30075 00005EAD 66BA7A03 <1> mov dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT 30076 00005EB1 B008 <1> mov al, 8 ; SET INIT LINE LOW 30077 00005EB3 EE <1> out dx, al 30078 <1> ;mov eax, 1000*4 ; ADJUST FOR INITIALIZATION DELAY LOOP 30079 00005EB4 B989080000 <1> mov ecx, WAIT_PRN_INIT ; (65536 micro seconds) 30080 <1> B90: ; INIT_LOOP 30081 <1> ;dec eax ; LOOP FOR RESET TO TAKE 30082 <1> ;jnz short B90 ; INIT_LOOP 30083 00005EB9 E807000000 <1> call WAIT_REFRESH ; (wait for 30 micro seconds) 30084 00005EBE E2F9 <1> loop B90 30085 00005EC0 B00C <1> mov al, 0Ch ; NO INTERRUPTS, NON AUTO LF, INIT HIGH 30086 00005EC2 EE <1> out dx, al 30087 00005EC3 EBA4 <1> jmp short B60 ; EXIT THROUGH STATUS ROUTINE 30088 <1> 30089 <1> 30090 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 30091 <1> ; ------------------------------------------------------------------- 30092 <1> ; 30093 <1> ;;Wait while printer initializes should be 65,536 microseconds. 30094 <1> ;;65536/30 = 2185 30095 <1> ; PUBLIC WAIT_PRN_INIT_LO 30096 <1> ;WAIT_PRN_INIT_LO DW 2185 30097 <1> ; PUBLIC WAIT_PRN_INIT_HI 30098 <1> ;WAIT_PRN_INIT_HI DW 0 30099 <1> ; 30100 <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022 30101 <1> ; 30102 <1> ;;Wait for printer not busy should be 1,080,000 microseconds. 30103 <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us. 30104 <1> ;;1,080,000 / 30 = 36,000 30105 <1> ; PUBLIC WAIT_PRN_NBUSY_LO 30106 <1> ;WAIT_PRN_NBUSY_LO DW 36000 30107 <1> ; PUBLIC WAIT_PRN_NBUSY_HI 30108 <1> ;WAIT_PRN_NBUSY_HI DB 0 30109 <1> ; 30110 <1> ;WAIT_PRN_NBUSY equ 36000 ; 12/06/2022 30111 <1> 30112 <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999) 30113 <1> ; ------------------------------------------ 30114 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 30115 <1> ; INPUT: BX:CX = number of refresh periods to wait 30116 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 30117 <1> ; OUTPUT: BX:CX destroyed. 30118 <1> ; 30119 <1> ; SAVES: AX (except when NO STACK) 30120 <1> ; 30121 <1> ; NOTES: This routine can be (and is) used with no stack. When 30122 <1> ; used this way, AX is assumed to be destroyed. 30123 <1> 30124 <1> WAIT_REFRESH: 30125 <1> ; 08/08/2022 30126 <1> ; 12/06/2022 30127 <1> ; Modified for Retro UNIX 386 v1.2 30128 <1> 30129 <1> ; (wait for 30 micro seconds) 30130 <1> 30131 <1> ; 08/08/2022 30132 <1> ;SYS1 equ 61h ; PORT_B 30133 <1> 30134 <1> WR_SHORT: 30135 00005EC5 50 <1> push eax 30136 <1> WR_STAT_0: 30137 00005EC6 E461 <1> in al, SYS1 ; wait for high to low 30138 00005EC8 A810 <1> test al, 10h ; transition on memory 30139 00005ECA 75FA <1> jnz short WR_STAT_0 30140 <1> WR_STAT_1: 30141 00005ECC E461 <1> in al, SYS1 30142 00005ECE A810 <1> test al, 10h 30143 00005ED0 74FA <1> jz short WR_STAT_1 30144 00005ED2 58 <1> pop eax 30145 00005ED3 C3 <1> retn 30146 30147 ; 07/03/2015 30148 ; Temporary Code 30149 display_disks: 30150 00005ED4 803D[8C620000]00 cmp byte [fd0_type], 0 30151 00005EDB 7605 jna short ddsks1 30152 00005EDD E87D000000 call pdskm 30153 ddsks1: 30154 00005EE2 803D[8D620000]00 cmp byte [fd1_type], 0 30155 00005EE9 760C jna short ddsks2 30156 00005EEB C605[53640000]31 mov byte [dskx], '1' 30157 00005EF2 E868000000 call pdskm 30158 ddsks2: 30159 00005EF7 803D[8E620000]00 cmp byte [hd0_type], 0 30160 00005EFE 7654 jna short ddsk6 30161 00005F00 66C705[51640000]68- mov word [dsktype], 'hd' 30162 00005F08 64 30163 00005F09 C605[53640000]30 mov byte [dskx], '0' 30164 00005F10 E84A000000 call pdskm 30165 ddsks3: 30166 00005F15 803D[8F620000]00 cmp byte [hd1_type], 0 30167 00005F1C 7636 jna short ddsk6 30168 00005F1E C605[53640000]31 mov byte [dskx], '1' 30169 00005F25 E835000000 call pdskm 30170 ddsks4: 30171 00005F2A 803D[90620000]00 cmp byte [hd2_type], 0 30172 00005F31 7621 jna short ddsk6 30173 00005F33 C605[53640000]32 mov byte [dskx], '2' 30174 00005F3A E820000000 call pdskm 30175 ddsks5: 30176 00005F3F 803D[91620000]00 cmp byte [hd3_type], 0 30177 00005F46 760C jna short ddsk6 30178 00005F48 C605[53640000]33 mov byte [dskx], '3' 30179 00005F4F E80B000000 call pdskm 30180 ddsk6: 30181 00005F54 BE[62640000] mov esi, nextline 30182 00005F59 E806000000 call pdskml 30183 pdskm_ok: 30184 00005F5E C3 retn 30185 pdskm: 30186 00005F5F BE[4F640000] mov esi, dsk_ready_msg 30187 pdskml: 30188 00005F64 AC lodsb 30189 00005F65 08C0 or al, al 30190 00005F67 74F5 jz short pdskm_ok 30191 00005F69 56 push esi 30192 00005F6A 31DB xor ebx, ebx ; 0 30193 ; Video page 0 (bl=0) 30194 00005F6C B407 mov ah, 07h ; Black background, 30195 ; light gray forecolor 30196 00005F6E E841B3FFFF call write_tty 30197 00005F73 5E pop esi 30198 00005F74 EBEE jmp short pdskml 30199 30200 00005F76 90 align 16 30201 30202 gdt: ; Global Descriptor Table 30203 ; (30/07/2015, conforming cs) 30204 ; (26/03/2015) 30205 ; (24/03/2015, tss) 30206 ; (19/03/2015) 30207 ; (29/12/2013) 30208 ; 30209 00005F80 0000000000000000 dw 0, 0, 0, 0 ; NULL descriptor 30210 ; 18/08/2014 30211 ; 08h kernel code segment, base = 00000000h 30212 00005F88 FFFF0000009ACF00 dw 0FFFFh, 0, 9A00h, 00CFh ; KCODE 30213 ; 10h kernel data segment, base = 00000000h 30214 00005F90 FFFF00000092CF00 dw 0FFFFh, 0, 9200h, 00CFh ; KDATA 30215 ; 1Bh user code segment, base address = 400000h ; CORE 30216 00005F98 FFFB000040FACF00 dw 0FBFFh, 0, 0FA40h, 00CFh ; UCODE 30217 ; 23h user data segment, base address = 400000h ; CORE 30218 00005FA0 FFFB000040F2CF00 dw 0FBFFh, 0, 0F240h, 00CFh ; UDATA 30219 ; Task State Segment 30220 00005FA8 6700 dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 30221 ; no IO permission in ring 3) 30222 gdt_tss0: 30223 00005FAA 0000 dw 0 ; TSS base address, bits 0-15 30224 gdt_tss1: 30225 00005FAC 00 db 0 ; TSS base address, bits 16-23 30226 ; 49h 30227 00005FAD E9 db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1) 30228 00005FAE 00 db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte) 30229 gdt_tss2: 30230 00005FAF 00 db 0 ; TSS base address, bits 24-31 30231 30232 gdt_end: 30233 ;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 30234 ;; Type= 1 (code)/C=0/R=1/A=0 30235 ; P= Present, DPL=0=ring 0, 1= user (0= system) 30236 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 30237 30238 ;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 30239 ;; Type= 0 (data)/E=0/W=1/A=0 30240 ; P= Present, DPL=0=ring 0, 1= user (0= system) 30241 ; 0= Data E= Expansion direction (1= down, 0= up) 30242 ; W= Writeable, A= Accessed 30243 30244 ;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 30245 ;; Type= 1 (code)/C=0/R=1/A=0 30246 ; P= Present, DPL=3=ring 3, 1= user (0= system) 30247 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 30248 30249 ;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 30250 ;; Type= 0 (data)/E=0/W=1/A=0 30251 ; P= Present, DPL=3=ring 3, 1= user (0= system) 30252 ; 0= Data E= Expansion direction (1= down, 0= up) 30253 30254 ;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3) 30255 30256 ;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 // 30257 ; = 100000h * 1000h (G=1) = 4GB 30258 ;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 // 30259 ; = FFC00h * 1000h (G=1) = 4GB - 4MB 30260 ; G= Granularity (1= 4KB), B= Big (32 bit), 30261 ; AVL= Available to programmers 30262 30263 gdtd: 30264 00005FB0 2F00 dw gdt_end - gdt - 1 ; Limit (size) 30265 00005FB2 [805F0000] dd gdt ; Address of the GDT 30266 30267 ; 20/08/2014 30268 idtd: 30269 00005FB6 FF01 dw idt_end - idt - 1 ; Limit (size) 30270 00005FB8 [00650000] dd idt ; Address of the IDT 30271 30272 align 4 30273 ; 21/08/2014 30274 ilist: 30275 ;times 32 dd cpu_except ; INT 0 to INT 1Fh 30276 ; 30277 ; Exception list 30278 ; 25/08/2014 30279 00005FBC [1D080000] dd exc0 ; 0h, Divide-by-zero Error 30280 00005FC0 [24080000] dd exc1 30281 00005FC4 [2B080000] dd exc2 30282 00005FC8 [32080000] dd exc3 30283 00005FCC [36080000] dd exc4 30284 00005FD0 [3A080000] dd exc5 30285 00005FD4 [3E080000] dd exc6 ; 06h, Invalid Opcode 30286 00005FD8 [42080000] dd exc7 30287 00005FDC [46080000] dd exc8 30288 00005FE0 [4A080000] dd exc9 30289 00005FE4 [4E080000] dd exc10 30290 00005FE8 [52080000] dd exc11 30291 00005FEC [56080000] dd exc12 30292 00005FF0 [5A080000] dd exc13 ; 0Dh, General Protection Fault 30293 00005FF4 [5E080000] dd exc14 ; 0Eh, Page Fault 30294 00005FF8 [62080000] dd exc15 30295 00005FFC [66080000] dd exc16 30296 00006000 [6A080000] dd exc17 30297 00006004 [6E080000] dd exc18 30298 00006008 [72080000] dd exc19 30299 0000600C [76080000] dd exc20 30300 00006010 [7A080000] dd exc21 30301 00006014 [7E080000] dd exc22 30302 00006018 [82080000] dd exc23 30303 0000601C [86080000] dd exc24 30304 00006020 [8A080000] dd exc25 30305 00006024 [8E080000] dd exc26 30306 00006028 [92080000] dd exc27 30307 0000602C [96080000] dd exc28 30308 00006030 [9A080000] dd exc29 30309 00006034 [9E080000] dd exc30 30310 00006038 [A2080000] dd exc31 30311 ; Interrupt list 30312 0000603C [58060000] dd timer_int ; INT 20h 30313 ;dd irq0 30314 00006040 [5C0B0000] dd keyb_int ; 27/08/2014 30315 ;dd irq1 30316 00006044 [77070000] dd irq2 30317 ; COM2 int 30318 00006048 [7B070000] dd irq3 30319 ; COM1 int 30320 0000604C [86070000] dd irq4 30321 00006050 [91070000] dd irq5 30322 ;DISKETTE_INT: ;06/02/2015 30323 00006054 [C81E0000] dd fdc_int ; 16/02/2015, IRQ 6 handler 30324 ;dd irq6 30325 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 30326 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 30327 00006058 [0D0B0000] dd default_irq7 ; 25/02/2015 30328 ;dd irq7 30329 ; Real Time Clock Interrupt 30330 0000605C [AB090000] dd rtc_int ; 23/02/2015, IRQ 8 handler 30331 ;dd irq8 ; INT 28h 30332 00006060 [A1070000] dd irq9 30333 00006064 [A5070000] dd irq10 30334 00006068 [A9070000] dd irq11 30335 0000606C [AD070000] dd irq12 30336 00006070 [B1070000] dd irq13 30337 ;HDISK_INT1: ;06/02/2015 30338 00006074 [98230000] dd hdc1_int ; 21/02/2015, IRQ 14 handler 30339 ;dd irq14 30340 ;HDISK_INT2: ;06/02/2015 30341 00006078 [BB230000] dd hdc2_int ; 21/02/2015, IRQ 15 handler 30342 ;dd irq15 ; INT 2Fh 30343 ; 14/08/2015 30344 0000607C [5D300000] dd sysent ; INT 30h (system calls) 30345 30346 ;dd ignore_int 30347 00006080 00000000 dd 0 30348 30349 ;;; 30350 ;;; 11/03/2015 30351 %include 'kybdata.s' ; KEYBOARD (BIOS) DATA 30352 <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - KYBDATA.INC 30353 <1> ; Last Modification: 11/06/2022 30354 <1> ; (Data Section for 'KEYBOARD.INC') 30355 <1> ; 30356 <1> ; ///////// KEYBOARD DATA /////////////// 30357 <1> 30358 <1> ; 11/03/2015 30359 <1> ; 05/12/2014 30360 <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 30361 <1> ; 03/06/86 KEYBOARD BIOS 30362 <1> 30363 <1> ;--------------------------------------------------------------------------------- 30364 <1> ; KEY IDENTIFICATION SCAN TABLES 30365 <1> ;--------------------------------------------------------------------------------- 30366 <1> 30367 <1> ;----- TABLES FOR ALT CASE ------------ 30368 <1> ;----- ALT-INPUT-TABLE 30369 00006084 524F50514B <1> K30: db 82,79,80,81,75 30370 00006089 4C4D474849 <1> db 76,77,71,72,73 ; 10 NUMBER ON KEYPAD 30371 <1> ;----- SUPER-SHIFT-TABLE 30372 0000608E 101112131415 <1> db 16,17,18,19,20,21 ; A-Z TYPEWRITER CHARS 30373 00006094 161718191E1F <1> db 22,23,24,25,30,31 30374 0000609A 202122232425 <1> db 32,33,34,35,36,37 30375 000060A0 262C2D2E2F30 <1> db 38,44,45,46,47,48 30376 000060A6 3132 <1> db 49,50 30377 <1> 30378 <1> ;----- TABLE OF SHIFT KEYS AND MASK VALUES 30379 <1> ;----- KEY_TABLE 30380 000060A8 52 <1> _K6: db INS_KEY ; INSERT KEY 30381 000060A9 3A4546381D <1> db CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY 30382 000060AE 2A36 <1> db LEFT_KEY,RIGHT_KEY 30383 <1> _K6L equ $-_K6 30384 <1> 30385 <1> ;----- MASK_TABLE 30386 000060B0 80 <1> _K7: db INS_SHIFT ; INSERT MODE SHIFT 30387 000060B1 4020100804 <1> db CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT 30388 000060B6 0201 <1> db LEFT_SHIFT,RIGHT_SHIFT 30389 <1> 30390 <1> ;----- TABLES FOR CTRL CASE ;---- CHARACTERS ------ 30391 000060B8 1BFF00FFFFFF <1> _K8: db 27,-1,0,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5 30392 000060BE 1EFFFFFFFF1F <1> db 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, - 30393 <1> ;db -1,127,-1,17,23,5 ; =, Bksp, Tab, Q, W, E 30394 000060C4 FF7F94111705 <1> db -1,127,148,17,23,5 ; 11/06/2022 30395 000060CA 12141915090F <1> db 18,20,25,21,9,15 ; R, T, Y, U, I, O 30396 000060D0 101B1D0AFF01 <1> db 16,27,29,10,-1,1 ; P, [, ], Enter, Ctrl, A 30397 000060D6 13040607080A <1> db 19,4,6,7,8,10 ; S, D, F, G, H, J 30398 000060DC 0B0CFFFFFFFF <1> db 11,12,-1,-1,-1,-1 ; K, L, :, ', `, LShift 30399 000060E2 1C1A18031602 <1> db 28,26,24,3,22,2 ; Bkslash, Z, X, C, V, B 30400 000060E8 0E0DFFFFFFFF <1> db 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift 30401 000060EE 96FF20FF <1> db 150,-1,' ',-1 ; *, ALT, Spc, CL 30402 <1> ; ;----- FUNCTIONS ------ 30403 000060F2 5E5F60616263 <1> db 94,95,96,97,98,99 ; F1 - F6 30404 000060F8 64656667FFFF <1> db 100,101,102,103,-1,-1 ; F7 - F10, NL, SL 30405 000060FE 778D848E738F <1> db 119,141,132,142,115,143 ; Home, Up, PgUp, -, Left, Pad5 30406 00006104 749075917692 <1> db 116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins 30407 0000610A 93FFFFFF898A <1> db 147,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12 30408 <1> 30409 <1> ;----- TABLES FOR LOWER CASE ---------- 30410 00006110 1B3132333435363738- <1> K10: db 27,'1234567890-=',8,9 30411 00006119 39302D3D0809 <1> 30412 0000611F 71776572747975696F- <1> db 'qwertyuiop[]',13,-1,'asdfghjkl;',39 30413 00006128 705B5D0DFF61736466- <1> 30414 00006131 67686A6B6C3B27 <1> 30415 00006138 60FF5C7A786376626E- <1> db 96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1 30416 00006141 6D2C2E2FFF2AFF20FF <1> 30417 <1> ;----- LC TABLE SCAN 30418 0000614A 3B3C3D3E3F <1> db 59,60,61,62,63 ; BASE STATE OF F1 - F10 30419 0000614F 4041424344 <1> db 64,65,66,67,68 30420 00006154 FFFF <1> db -1,-1 ; NL, SL 30421 <1> 30422 <1> ;----- KEYPAD TABLE 30423 00006156 474849FF4BFF <1> K15: db 71,72,73,-1,75,-1 ; BASE STATE OF KEYPAD KEYS 30424 0000615C 4DFF4F50515253 <1> db 77,-1,79,80,81,82,83 30425 00006163 FFFF5C8586 <1> db -1,-1,92,133,134 ; SysRq, Undef, WT, F11, F12 30426 <1> 30427 <1> ;----- TABLES FOR UPPER CASE ---------- 30428 00006168 1B21402324255E262A- <1> K11: db 27,'!@#$%',94,'&*()_+',8,0 30429 00006171 28295F2B0800 <1> 30430 00006177 51574552545955494F- <1> db 'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"' 30431 00006180 507B7D0DFF41534446- <1> 30432 00006189 47484A4B4C3A22 <1> 30433 00006190 7EFF7C5A584356424E- <1> db 126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1 30434 00006199 4D3C3E3FFF2AFF20FF <1> 30435 <1> ;----- UC TABLE SCAN 30436 000061A2 5455565758 <1> K12: db 84,85,86,87,88 ; SHIFTED STATE OF F1 - F10 30437 000061A7 595A5B5C5D <1> db 89,90,91,92,93 30438 000061AC FFFF <1> db -1,-1 ; NL, SL 30439 <1> 30440 <1> ;----- NUM STATE TABLE 30441 000061AE 3738392D3435362B31- <1> K14: db '789-456+1230.' ; NUMLOCK STATE OF KEYPAD KEYS 30442 000061B7 3233302E <1> 30443 <1> ; 30444 000061BB FFFF7C8788 <1> db -1,-1,124,135,136 ; SysRq, Undef, WT, F11, F12 30445 <1> 30446 <1> Align 4 30447 <1> ;---------------------------------------- 30448 <1> ; VIDEO DISPLAY DATA AREA ; 30449 <1> ;---------------------------------------- 30450 000061C0 03 <1> CRT_MODE db 3 ; CURRENT DISPLAY MODE (TYPE) 30451 000061C1 29 <1> CRT_MODE_SET db 29h ; CURRENT SETTING OF THE 3X8 REGISTER 30452 <1> ; (29h default setting for video mode 3) 30453 <1> ; Mode Select register Bits 30454 <1> ; BIT 0 - 80x25 (1), 40x25 (0) 30455 <1> ; BIT 1 - ALPHA (0), 320x200 GRAPHICS (1) 30456 <1> ; BIT 2 - COLOR (0), BW (1) 30457 <1> ; BIT 3 - Video Sig. ENABLE (1), DISABLE (0) 30458 <1> ; BIT 4 - 640x200 B&W Graphics Mode (1) 30459 <1> ; BIT 5 - ALPHA mode BLINKING (1) 30460 <1> ; BIT 6, 7 - Not Used 30461 <1> 30462 <1> ; Mode 0 - 2Ch = 101100b ; 40x25 text, 16 gray colors 30463 <1> ; Mode 1 - 28h = 101000b ; 40x25 text, 16 fore colors, 8 back colors 30464 <1> ; Mode 2 - 2Dh = 101101b ; 80x25 text, 16 gray colors 30465 <1> ; MODE 3 - 29h = 101001b ; 80x25 text, 16 fore color, 8 back color 30466 <1> ; Mode 4 - 2Ah = 101010b ; 320x200 graphics, 4 colors 30467 <1> ; Mode 5 - 2Eh = 101110b ; 320x200 graphics, 4 gray colors 30468 <1> ; Mode 6 - 1Eh = 011110b ; 640x200 graphics, 2 colors 30469 <1> ; Mode 7 - 29h = 101001b ; 80x25 text, black & white colors 30470 <1> ; Mode & 37h = Video signal OFF 30471 <1> 30472 <1> 30473 <1> ; 26/08/2014 30474 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014) 30475 <1> ; Derived from IBM "pc-at" 30476 <1> ; rombios source code (06/10/1985) 30477 <1> ; 'dseg.inc' 30478 <1> 30479 <1> ;---------------------------------------; 30480 <1> ; SYSTEM DATA AREA ; 30481 <1> ;---------------------------------------- 30482 000061C2 00 <1> BIOS_BREAK db 0 ; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED 30483 <1> 30484 <1> ;---------------------------------------- 30485 <1> ; KEYBOARD DATA AREAS ; 30486 <1> ;---------------------------------------- 30487 <1> 30488 000061C3 00 <1> KB_FLAG db 0 ; KEYBOARD SHIFT STATE AND STATUS FLAGS 30489 000061C4 00 <1> KB_FLAG_1 db 0 ; SECOND BYTE OF KEYBOARD STATUS 30490 000061C5 00 <1> KB_FLAG_2 db 0 ; KEYBOARD LED FLAGS 30491 000061C6 00 <1> KB_FLAG_3 db 0 ; KEYBOARD MODE STATE AND TYPE FLAGS 30492 000061C7 00 <1> ALT_INPUT db 0 ; STORAGE FOR ALTERNATE KEY PAD ENTRY 30493 000061C8 [D8610000] <1> BUFFER_START dd KB_BUFFER ; OFFSET OF KEYBOARD BUFFER START 30494 000061CC [F8610000] <1> BUFFER_END dd KB_BUFFER + 32 ; OFFSET OF END OF BUFFER 30495 000061D0 [D8610000] <1> BUFFER_HEAD dd KB_BUFFER ; POINTER TO HEAD OF KEYBOARD BUFFER 30496 000061D4 [D8610000] <1> BUFFER_TAIL dd KB_BUFFER ; POINTER TO TAIL OF KEYBOARD BUFFER 30497 <1> ; ------ HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY 30498 000061D8 0000 <1> KB_BUFFER times 16 dw 0 ; ROOM FOR 16 SCAN CODE ENTRIES 30499 <1> 30500 <1> ; /// End Of KEYBOARD DATA /// 30501 %include 'vidata.s' ; VIDEO (BIOS) DATA 30502 <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC 30503 <1> ; Last Modification: 11/03/2015 30504 <1> ; (Data section for 'VIDEO.INC') 30505 <1> ; 30506 <1> ; ///////// VIDEO DATA /////////////// 30507 <1> 30508 <1> video_params: 30509 <1> ; 02/09/2014 (Retro UNIX 386 v1) 30510 <1> ;ORGS.ASM ----- 06/10/85 COMPATIBILITY MODULE 30511 <1> ; VIDEO MODE 3 30512 000061F8 71505A0A1F0619 <1> db 71h,50h,5Ah,0Ah,1Fh,6,19h ; SET UP FOR 80X25 30513 000061FF 1C02070607 <1> db 1Ch,2,7,6,7 ; cursor start = 6, cursor stop = 7 30514 00006204 00000000 <1> db 0,0,0,0 30515 <1> 30516 <1> ; /// End Of VIDEO DATA /// 30517 %include 'diskdata.s' ; DISK (BIOS) DATA (initialized) 30518 <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - DISKBSS.INC 30519 <1> ; Last Modification: 12/07/2022 30520 <1> ; ***************************************************************************** 30521 <1> ; (Initialized Disk Parameters Data section for 'DISKIO.INC') 30522 <1> ; ***************************************************************************** 30523 <1> ; Ref: Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKDATA.INC - 11/07/2022 30524 <1> 30525 <1> ;---------------------------------------- 30526 <1> ; 80286 INTERRUPT LOCATIONS : 30527 <1> ; REFERENCED BY POST & BIOS : 30528 <1> ;---------------------------------------- 30529 <1> 30530 00006208 [6B620000] <1> DISK_POINTER: dd MD_TBL6 ; Pointer to Diskette Parameter Table 30531 <1> 30532 <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014 30533 <1> ;---------------------------------------------------------------- 30534 <1> ; DISK_BASE : 30535 <1> ; THIS IS THE SET OF PARAMETERS REQUIRED FOR : 30536 <1> ; DISKETTE OPERATION. THEY ARE POINTED AT BY THE : 30537 <1> ; DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS, : 30538 <1> ; BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT : 30539 <1> ;---------------------------------------------------------------- 30540 <1> 30541 <1> ;DISK_BASE: 30542 <1> ; DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 30543 <1> ; DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 30544 <1> ; DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 30545 <1> ; DB 2 ; 512 BYTES/SECTOR 30546 <1> ; ;DB 15 ; EOT (LAST SECTOR ON TRACK) 30547 <1> ; db 18 ; (EOT for 1.44MB diskette) 30548 <1> ; DB 01BH ; GAP LENGTH 30549 <1> ; DB 0FFH ; DTL 30550 <1> ; ;DB 054H ; GAP LENGTH FOR FORMAT 30551 <1> ; db 06ch ; (for 1.44MB dsikette) 30552 <1> ; DB 0F6H ; FILL BYTE FOR FORMAT 30553 <1> ; DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 30554 <1> ; DB 8 ; MOTOR START TIME (1/8 SECONDS) 30555 <1> 30556 <1> ;---------------------------------------- 30557 <1> ; ROM BIOS DATA AREAS : 30558 <1> ;---------------------------------------- 30559 <1> 30560 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 30561 <1> 30562 <1> ;@EQUIP_FLAG DW ? ; INSTALLED HARDWARE FLAGS 30563 <1> 30564 <1> ;---------------------------------------- 30565 <1> ; DISKETTE DATA AREAS : 30566 <1> ;---------------------------------------- 30567 <1> 30568 <1> ;@SEEK_STATUS DB ? ; DRIVE RECALIBRATION STATUS 30569 <1> ; ; BIT 3-0 = DRIVE 3-0 RECALIBRATION 30570 <1> ; ; BEFORE NEXT SEEK IF BIT IS = 0 30571 <1> ;@MOTOR_STATUS DB ? ; MOTOR STATUS 30572 <1> ; ; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING 30573 <1> ; ; BIT 7 = CURRENT OPERATION IS A WRITE 30574 <1> ;@MOTOR_COUNT DB ? ; TIME OUT COUNTER FOR MOTOR(S) TURN OFF 30575 <1> ;@DSKETTE_STATUS DB ? ; RETURN CODE STATUS BYTE 30576 <1> ; ; CMD_BLOCK IN STACK FOR DISK OPERATION 30577 <1> ;@NEC_STATUS DB 7 DUP(?) ; STATUS BYTES FROM DISKETTE OPERATION 30578 <1> 30579 <1> ;---------------------------------------- 30580 <1> ; POST AND BIOS WORK DATA AREA : 30581 <1> ;---------------------------------------- 30582 <1> 30583 <1> ;@INTR_FLAG DB ? ; FLAG INDICATING AN INTERRUPT HAPPENED 30584 <1> 30585 <1> ;---------------------------------------- 30586 <1> ; TIMER DATA AREA : 30587 <1> ;---------------------------------------- 30588 <1> 30589 <1> ; 17/12/2014 (IRQ 0 - INT 08H) 30590 <1> ;TIMER_LOW equ 46Ch ; Timer ticks (counter) @ 40h:006Ch 30591 <1> ;TIMER_HIGH equ 46Eh ; (18.2 timer ticks per second) 30592 <1> ;TIMER_OFL equ 470h ; Timer - 24 hours flag @ 40h:0070h 30593 <1> 30594 <1> ;---------------------------------------- 30595 <1> ; ADDITIONAL MEDIA DATA : 30596 <1> ;---------------------------------------- 30597 <1> 30598 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 30599 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 30600 <1> ; DB ? ; DRIVE 1 MEDIA STATE 30601 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 30602 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 30603 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 30604 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 30605 <1> 30606 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 30607 <1> 30608 <1> ;-------------------------------------------------------- 30609 <1> ; DRIVE TYPE TABLE : 30610 <1> ;-------------------------------------------------------- 30611 <1> ; 16/02/2015 (unix386.s, 32 bit modifications) 30612 <1> DR_TYPE: 30613 0000620C 01 <1> DB 01 ;DRIVE TYPE, MEDIA TABLE 30614 <1> ;DW MD_TBL1 30615 0000620D [2A620000] <1> dd MD_TBL1 30616 00006211 82 <1> DB 02+BIT7ON 30617 <1> ;DW MD_TBL2 30618 00006212 [37620000] <1> dd MD_TBL2 30619 00006216 02 <1> DR_DEFAULT: DB 02 30620 <1> ;DW MD_TBL3 30621 00006217 [44620000] <1> dd MD_TBL3 30622 0000621B 03 <1> DB 03 30623 <1> ;DW MD_TBL4 30624 0000621C [51620000] <1> dd MD_TBL4 30625 00006220 84 <1> DB 04+BIT7ON 30626 <1> ;DW MD_TBL5 30627 00006221 [5E620000] <1> dd MD_TBL5 30628 00006225 04 <1> DB 04 30629 <1> ;DW MD_TBL6 30630 00006226 [6B620000] <1> dd MD_TBL6 30631 <1> DR_TYPE_E equ $ ; END OF TABLE 30632 <1> ;DR_CNT EQU (DR_TYPE_E-DR_TYPE)/3 30633 <1> DR_CNT equ (DR_TYPE_E-DR_TYPE)/5 30634 <1> ;-------------------------------------------------------- 30635 <1> ; MEDIA/DRIVE PARAMETER TABLES : 30636 <1> ;-------------------------------------------------------- 30637 <1> ;-------------------------------------------------------- 30638 <1> ; 360 KB MEDIA IN 360 KB DRIVE : 30639 <1> ;-------------------------------------------------------- 30640 <1> MD_TBL1: 30641 0000622A DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 30642 0000622B 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 30643 0000622C 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 30644 0000622D 02 <1> DB 2 ; 512 BYTES/SECTOR 30645 0000622E 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 30646 0000622F 2A <1> DB 02AH ; GAP LENGTH 30647 00006230 FF <1> DB 0FFH ; DTL 30648 00006231 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 30649 00006232 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 30650 00006233 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 30651 00006234 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 30652 00006235 27 <1> DB 39 ; MAX. TRACK NUMBER 30653 00006236 80 <1> DB RATE_250 ; DATA TRANSFER RATE 30654 <1> ;-------------------------------------------------------- 30655 <1> ; 360 KB MEDIA IN 1.2 MB DRIVE : 30656 <1> ;-------------------------------------------------------- 30657 <1> MD_TBL2: 30658 00006237 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 30659 00006238 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 30660 00006239 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 30661 0000623A 02 <1> DB 2 ; 512 BYTES/SECTOR 30662 0000623B 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 30663 0000623C 2A <1> DB 02AH ; GAP LENGTH 30664 0000623D FF <1> DB 0FFH ; DTL 30665 0000623E 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 30666 0000623F F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 30667 00006240 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 30668 00006241 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 30669 00006242 27 <1> DB 39 ; MAX. TRACK NUMBER 30670 00006243 40 <1> DB RATE_300 ; DATA TRANSFER RATE 30671 <1> ;-------------------------------------------------------- 30672 <1> ; 1.2 MB MEDIA IN 1.2 MB DRIVE : 30673 <1> ;-------------------------------------------------------- 30674 <1> MD_TBL3: 30675 00006244 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 30676 00006245 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 30677 00006246 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 30678 00006247 02 <1> DB 2 ; 512 BYTES/SECTOR 30679 00006248 0F <1> DB 15 ; EOT (LAST SECTOR ON TRACK) 30680 00006249 1B <1> DB 01BH ; GAP LENGTH 30681 0000624A FF <1> DB 0FFH ; DTL 30682 0000624B 54 <1> DB 054H ; GAP LENGTH FOR FORMAT 30683 0000624C F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 30684 0000624D 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 30685 0000624E 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 30686 0000624F 4F <1> DB 79 ; MAX. TRACK NUMBER 30687 00006250 00 <1> DB RATE_500 ; DATA TRANSFER RATE 30688 <1> ;-------------------------------------------------------- 30689 <1> ; 720 KB MEDIA IN 720 KB DRIVE : 30690 <1> ;-------------------------------------------------------- 30691 <1> MD_TBL4: 30692 00006251 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 30693 00006252 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 30694 00006253 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 30695 00006254 02 <1> DB 2 ; 512 BYTES/SECTOR 30696 00006255 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 30697 00006256 2A <1> DB 02AH ; GAP LENGTH 30698 00006257 FF <1> DB 0FFH ; DTL 30699 00006258 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 30700 00006259 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 30701 0000625A 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 30702 0000625B 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 30703 0000625C 4F <1> DB 79 ; MAX. TRACK NUMBER 30704 0000625D 80 <1> DB RATE_250 ; DATA TRANSFER RATE 30705 <1> ;-------------------------------------------------------- 30706 <1> ; 720 KB MEDIA IN 1.44 MB DRIVE : 30707 <1> ;-------------------------------------------------------- 30708 <1> MD_TBL5: 30709 0000625E DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 30710 0000625F 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 30711 00006260 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 30712 00006261 02 <1> DB 2 ; 512 BYTES/SECTOR 30713 00006262 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 30714 00006263 2A <1> DB 02AH ; GAP LENGTH 30715 00006264 FF <1> DB 0FFH ; DTL 30716 00006265 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 30717 00006266 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 30718 00006267 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 30719 00006268 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 30720 00006269 4F <1> DB 79 ; MAX. TRACK NUMBER 30721 0000626A 80 <1> DB RATE_250 ; DATA TRANSFER RATE 30722 <1> ;-------------------------------------------------------- 30723 <1> ; 1.44 MB MEDIA IN 1.44 MB DRIVE : 30724 <1> ;-------------------------------------------------------- 30725 <1> MD_TBL6: 30726 0000626B AF <1> DB 10101111B ; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE 30727 0000626C 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 30728 0000626D 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 30729 0000626E 02 <1> DB 2 ; 512 BYTES/SECTOR 30730 0000626F 12 <1> DB 18 ; EOT (LAST SECTOR ON TRACK) 30731 00006270 1B <1> DB 01BH ; GAP LENGTH 30732 00006271 FF <1> DB 0FFH ; DTL 30733 00006272 6C <1> DB 06CH ; GAP LENGTH FOR FORMAT 30734 00006273 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 30735 00006274 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 30736 00006275 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 30737 00006276 4F <1> DB 79 ; MAX. TRACK NUMBER 30738 00006277 00 <1> DB RATE_500 ; DATA TRANSFER RATE 30739 <1> 30740 <1> 30741 <1> ; << diskette.inc >> 30742 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 30743 <1> ; 30744 <1> ;---------------------------------------- 30745 <1> ; ROM BIOS DATA AREAS : 30746 <1> ;---------------------------------------- 30747 <1> 30748 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 30749 <1> 30750 <1> ;---------------------------------------- 30751 <1> ; FIXED DISK DATA AREAS : 30752 <1> ;---------------------------------------- 30753 <1> 30754 <1> ;DISK_STATUS1: DB 0 ; FIXED DISK STATUS 30755 <1> ;HF_NUM: DB 0 ; COUNT OF FIXED DISK DRIVES 30756 <1> ;CONTROL_BYTE: DB 0 ; HEAD CONTROL BYTE 30757 <1> ;@PORT_OFF DB ? ; RESERVED (PORT OFFSET) 30758 <1> 30759 <1> ;---------------------------------------- 30760 <1> ; ADDITIONAL MEDIA DATA : 30761 <1> ;---------------------------------------- 30762 <1> 30763 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 30764 <1> ;HF_STATUS DB 0 ; STATUS REGISTER 30765 <1> ;HF_ERROR DB 0 ; ERROR REGISTER 30766 <1> ;HF_INT_FLAG DB 0 ; FIXED DISK INTERRUPT FLAG 30767 <1> ;HF_CNTRL DB 0 ; COMBO FIXED DISK/DISKETTE CARD BIT 0=1 30768 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 30769 <1> ; DB ? ; DRIVE 1 MEDIA STATE 30770 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 30771 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 30772 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 30773 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 30774 <1> 30775 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 30776 <1> ; 30777 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 30778 <1> 30779 <1> ERR_TBL: 30780 00006278 E0 <1> db NO_ERR 30781 00006279 024001BB <1> db BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR 30782 0000627D 04BB100A <1> db RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR 30783 <1> 30784 <1> ; 11/07/2022 30785 <1> ; 17/12/2014 (mov ax, [cfd]) 30786 <1> ; 11/12/2014 30787 <1> ;cfd: db 0 ; current floppy drive (for GET_PARM) 30788 <1> ; 17/12/2014 ; instead of 'DISK_POINTER' 30789 <1> ;pfd: db 1 ; previous floppy drive (for GET_PARM) 30790 <1> ; (initial value of 'pfd 30791 <1> ; must be different then 'cfd' value 30792 <1> ; to force updating/initializing 30793 <1> ; current drive parameters) 30794 <1> 30795 <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 30796 00006281 FF <1> pfd: db 0FFh 30797 <1> 30798 <1> align 2 30799 <1> 30800 00006282 F001 <1> HF_PORT: dw 1F0h ; Default = 1F0h 30801 <1> ; (170h) 30802 00006284 F603 <1> HF_REG_PORT: dw 3F6h ; HF_PORT + 206h 30803 <1> 30804 <1> ; 05/01/2015 30805 00006286 00 <1> hf_m_s: db 0 ; (0 = Master, 1 = Slave) 30806 <1> 30807 <1> ; ***************************************************************************** 30808 ;;; 30809 30810 00006287 90 align 2 30811 30812 ; 12/11/2014 (Retro UNIX 386 v1) 30813 00006288 00 boot_drv: db 0 ; boot drive number (physical) 30814 ; 24/11/2014 30815 00006289 00 drv: db 0 30816 0000628A 00 last_drv: db 0 ; last hdd 30817 0000628B 00 hdc: db 0 ; number of hard disk drives 30818 ; (present/detected) 30819 ; 30820 ; 24/11/2014 (Retro UNIX 386 v1) 30821 ; Physical drive type & flags 30822 0000628C 00 fd0_type: db 0 ; floppy drive type 30823 0000628D 00 fd1_type: db 0 ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt) 30824 ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt) 30825 ; 3 = 720 Kb, 80 track, 3.5" (9 spt) 30826 ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt) 30827 ; 1 = 360 Kb, 40 track, 5.25" (9 spt) 30828 0000628E 00 hd0_type: db 0 ; EDD status for hd0 (bit 7 - present flag) 30829 0000628F 00 hd1_type: db 0 ; EDD status for hd1 (bit 7 - present flag) 30830 00006290 00 hd2_type: db 0 ; EDD status for hd2 (bit 7 - present flag) 30831 00006291 00 hd3_type: db 0 ; EDD status for hd3 (bit 7 - present flag) 30832 ; bit 0 - Fixed disk access subset supported 30833 ; bit 1 - Drive locking and ejecting 30834 ; bit 2 - Enhanced disk drive support 30835 ; bit 3 - Reserved (64 bit EDD support) 30836 ; (If bit 0 is '1' Retro UNIX 386 v1 30837 ; will interpret it as 'LBA ready'!) 30838 30839 ; 12/07/2022 30840 ; (drv.cylinders, drv.spt, drv.spt will not be used now on) 30841 ; ('diskio.inc') 30842 ; ((spt and heads and cylinder counts will be taken from DPT)) 30843 30844 ; 11/03/2015 - 10/07/2015 30845 ;drv.cylinders: dw 0,0,0,0,0,0,0 30846 ;drv.heads: dw 0,0,0,0,0,0,0 30847 ;drv.spt: dw 0,0,0,0,0,0,0 30848 ; 12/07/2022 - 11/03/2015 30849 00006292 000000000000000000- drv.size: dd 0,0,0,0,0,0,0 30850 0000629B 000000000000000000- 30851 000062A4 000000000000000000- 30852 000062AD 00 30853 000062AE 00000000000000 drv.status: db 0,0,0,0,0,0,0 30854 000062B5 00000000000000 drv.error: db 0,0,0,0,0,0,0 30855 ; 30856 30857 ; 27/08/2014 30858 scr_row: 30859 000062BC E0810B00 dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3 30860 scr_col: 30861 000062C0 00000000 dd 0 30862 30863 ;; 14/08/2015 30864 ;;msgPM: 30865 ;; db "Protected mode and paging are ENABLED ... ", 0 30866 msgKVER: 30867 ;;;;db "Retro UNIX 386 v1.2 - Kernel v0.2.2.0 [18/04/2022]", 0 30868 ;;;db "Retro UNIX 386 v1.2 - Kernel v0.2.2.1 [08/06/2022]", 0 30869 ;;db "Retro UNIX 386 v1.2 - Kernel v0.2.2.2 [14/06/2022]", 0 30870 ;db "Retro UNIX 386 v1.2 - Kernel v0.2.2.3 [08/08/2022]", 0 30871 000062C4 526574726F20554E49- db "Retro UNIX 386 v1.2 - Kernel v0.2.2.4 [27/12/2022]", 0 30872 000062CD 58203338362076312E- 30873 000062D6 32202D204B65726E65- 30874 000062DF 6C2076302E322E322E- 30875 000062E8 34205B32372F31322F- 30876 000062F1 323032325D00 30877 30878 000062F7 90 align 2 30879 30880 ; 20/08/2014 30881 ; /* This is the default interrupt "handler" :-) */ 30882 ; Linux v0.12 (head.s) 30883 int_msg: 30884 000062F8 556E6B6E6F776E2069- db "Unknown interrupt ! ", 0 30885 00006301 6E7465727275707420- 30886 0000630A 212000 30887 30888 0000630D 90 align 2 30889 30890 ; 21/08/2014 30891 timer_msg: 30892 0000630E 49525120302028494E- db "IRQ 0 (INT 20h) ! Timer Interrupt : " 30893 00006317 542032306829202120- 30894 00006320 54696D657220496E74- 30895 00006329 657272757074203A20 30896 tcountstr: 30897 00006332 303030303020 db "00000 " 30898 00006338 00 db 0 30899 30900 00006339 90 align 2 30901 ; 21/08/2014 30902 exc_msg: 30903 0000633A 435055206578636570- db "CPU exception ! " 30904 00006343 74696F6E202120 30905 excnstr: ; 25/08/2014 30906 0000634A 3F3F68202045495020- db "??h", " EIP : " 30907 00006353 3A20 30908 EIPstr: ; 29/08/2014 30909 00006355 00 times 12 db 0 30910 rtc_msg: 30911 00006361 5265616C2054696D65- db "Real Time Clock - " 30912 0000636A 20436C6F636B202D20 30913 datestr: 30914 00006373 30302F30302F303030- db "00/00/0000" 30915 0000637C 30 30916 0000637D 20 db " " 30917 daystr: 30918 0000637E 44415920 db "DAY " 30919 timestr: 30920 00006382 30303A30303A3030 db "00:00:00" 30921 0000638A 20 db " " 30922 0000638B 00 db 0 30923 30924 daytmp: 30925 ; 28/02/2015 30926 0000638C 3F3F3F2053554E204D- db "??? SUN MON TUE WED THU FRI SAT " 30927 00006395 4F4E20545545205745- 30928 0000639E 442054485520465249- 30929 000063A7 2053415420 30930 30931 000063AC FF ptime_seconds: db 0FFh 30932 30933 ; 23/02/2015 30934 ; 25/08/2014 30935 ;scounter: 30936 ; db 5 30937 ; db 19 30938 30939 ; 28/11/2021 30940 ;; 05/11/2014 30941 ;msg_out_of_memory: 30942 ; db 07h, 0Dh, 0Ah 30943 ; db 'Insufficient memory ! (Minimum 2 MB memory is needed.)' 30944 ; db 0Dh, 0Ah, 0 30945 ; 30946 setup_error_msg: 30947 000063AD 0D0A db 0Dh, 0Ah 30948 000063AF 4469736B2053657475- db 'Disk Setup Error!' 30949 000063B8 70204572726F7221 30950 000063C0 0D0A00 db 0Dh, 0Ah,0 30951 30952 ; 02/09/2014 (Retro UNIX 386 v1) 30953 ;crt_ulc: db 0 ; upper left column (for scroll) 30954 ; db 0 ; upper left row (for scroll) 30955 30956 ;crt_lrc: db 79 ; lower right column (for scroll) 30957 ; db 24 ; lower right row (for scroll) 30958 30959 ; 06/11/2014 (Temporary Data) 30960 ; Memory Information message 30961 ; 14/08/2015 30962 msg_memory_info: 30963 000063C3 07 db 07h 30964 000063C4 0D0A db 0Dh, 0Ah 30965 ;db "MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah 30966 000063C6 546F74616C206D656D- db "Total memory : " 30967 000063CF 6F7279203A20 30968 mem_total_b_str: ; 10 digits 30969 000063D5 303030303030303030- db "0000000000 bytes", 0Dh, 0Ah 30970 000063DE 302062797465730D0A 30971 000063E7 202020202020202020- db " ", 20h, 20h, 20h 30972 000063F0 202020202020202020 30973 mem_total_p_str: ; 7 digits 30974 000063F9 303030303030302070- db "0000000 pages", 0Dh, 0Ah 30975 00006402 616765730D0A 30976 00006408 0D0A db 0Dh, 0Ah 30977 0000640A 46726565206D656D6F- db "Free memory : " 30978 00006413 727920203A20 30979 free_mem_b_str: ; 10 digits 30980 00006419 3F3F3F3F3F3F3F3F3F- db "?????????? bytes", 0Dh, 0Ah 30981 00006422 3F2062797465730D0A 30982 0000642B 202020202020202020- db " ", 20h, 20h, 20h 30983 00006434 202020202020202020 30984 free_mem_p_str: ; 7 digits 30985 0000643D 3F3F3F3F3F3F3F2070- db "??????? pages", 0Dh, 0Ah 30986 00006446 616765730D0A 30987 0000644C 0D0A00 db 0Dh, 0Ah, 0 30988 30989 dsk_ready_msg: 30990 0000644F 0D0A db 0Dh, 0Ah 30991 dsktype: 30992 00006451 6664 db 'fd' 30993 dskx: 30994 00006453 30 db '0' 30995 00006454 20 db 20h 30996 00006455 697320524541445920- db 'is READY ...' 30997 0000645E 2E2E2E 30998 00006461 00 db 0 30999 nextline: 31000 00006462 0D0A00 db 0Dh, 0Ah, 0 31001 31002 ; KERNEL - SYSINIT Messages 31003 ; 24/08/2015 31004 ; 13/04/2015 - (Retro UNIX 386 v1 Beginning) 31005 ; 14/07/2013 31006 ;kernel_init_err_msg: 31007 ; db 0Dh, 0Ah 31008 ; db 07h 31009 ; db 'Kernel initialization ERROR !' 31010 ; db 0Dh, 0Ah, 0 31011 ; 24/08/2015 31012 ;;; (temporary kernel init message has been removed 31013 ;;; from 'sys_init' code) 31014 ;kernel_init_ok_msg: 31015 ; db 0Dh, 0Ah 31016 ; db 07h 31017 ; db 'Welcome to Retro UNIX 386 v1.1 Operating System !' 31018 ; db 0Dh, 0Ah 31019 ; db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)' 31020 ; db 0Dh, 0Ah, 0 31021 panic_msg: 31022 00006465 0D0A07 db 0Dh, 0Ah, 07h 31023 00006468 4552524F523A204B65- db 'ERROR: Kernel Panic !' 31024 00006471 726E656C2050616E69- 31025 0000647A 632021 31026 0000647D 0D0A00 db 0Dh, 0Ah, 0 31027 etc_init_err_msg: 31028 00006480 0D0A db 0Dh, 0Ah 31029 00006482 07 db 07h 31030 00006483 4552524F523A202F65- db 'ERROR: /etc/init !?' 31031 0000648C 74632F696E69742021- 31032 00006495 3F 31033 00006496 0D0A00 db 0Dh, 0Ah, 0 31034 31035 ; 10/05/2015 31036 badsys_msg: 31037 00006499 0D0A db 0Dh, 0Ah 31038 0000649B 07 db 07h 31039 0000649C 496E76616C69642053- db 'Invalid System Call !' 31040 000064A5 797374656D2043616C- 31041 000064AE 6C2021 31042 000064B1 0D0A db 0Dh, 0Ah 31043 000064B3 4541583A20 db 'EAX: ' 31044 bsys_msg_eax: 31045 000064B8 303030303030303068 db '00000000h' 31046 000064C1 0D0A db 0Dh, 0Ah 31047 000064C3 4549503A20 db 'EIP: ' 31048 bsys_msg_eip: 31049 000064C8 303030303030303068 db '00000000h' 31050 000064D1 0D0A00 db 0Dh, 0Ah, 0 31051 31052 BSYS_M_SIZE equ $ - badsys_msg 31053 31054 align 2 31055 31056 ; EPOCH Variables 31057 ; 13/04/2015 - Retro UNIX 386 v1 Beginning 31058 ; 09/04/2013 epoch variables 31059 ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013 31060 ; 31061 000064D4 B207 year: dw 1970 31062 ;month: dw 1 31063 ;day: dw 1 31064 ;hour: dw 0 31065 ;minute: dw 0 31066 ;second: dw 0 31067 ; 02/06/2022 31068 000064D6 01 month: db 1 31069 000064D7 01 day: db 1 31070 000064D8 01 hour: db 1 31071 000064D9 01 minute: db 1 31072 000064DA 01 second: db 1 31073 000064DB 01 db 1 31074 31075 DMonth: 31076 000064DC 0000 dw 0 31077 000064DE 1F00 dw 31 31078 000064E0 3B00 dw 59 31079 000064E2 5A00 dw 90 31080 000064E4 7800 dw 120 31081 000064E6 9700 dw 151 31082 000064E8 B500 dw 181 31083 000064EA D400 dw 212 31084 000064EC F300 dw 243 31085 000064EE 1101 dw 273 31086 000064F0 3001 dw 304 31087 000064F2 4E01 dw 334 31088 31089 ; 02/01/2022 (Retro UNIX 386 v1.2) 31090 ; 04/11/2014 (Retro UNIX 386 v1) 31091 000064F4 0000 mem_1m_1k: dw 0 ; Number of contiguous KB between 31092 ; 1 and 16 MB, max. 3C00h = 15 MB. 31093 000064F6 0000 dw 0 ; 02/01/2022 (Retro UNIX 386 v1.2) 31094 000064F8 0000 mem_16m_64k: dw 0 ; Number of contiguous 64 KB blocks 31095 ; between 16 MB and 4 GB. 31096 000064FA 0000 dw 0 ; 02/01/2022 (Retro UNIX 386 v1.2) 31097 31098 ; 01/01/2022 31099 KEND: 31100 31101 000064FC 90 align 16 31102 31103 bss_start: 31104 31105 ABSOLUTE bss_start 31106 31107 ; 11/03/2015 31108 ; Interrupt Descriptor Table (20/08/2014) 31109 idt: 31110 00006500 resb 64*8 ; INT 0 to INT 3Fh 31111 idt_end: 31112 31113 ;alignb 4 31114 31115 task_state_segment: 31116 ; 24/03/2015 31117 00006700 tss.link: resw 1 31118 00006702 resw 1 31119 ; tss offset 4 31120 00006704 tss.esp0: resd 1 31121 00006708 tss.ss0: resw 1 31122 0000670A resw 1 31123 0000670C tss.esp1: resd 1 31124 00006710 tss.ss1: resw 1 31125 00006712 resw 1 31126 00006714 tss.esp2: resd 1 31127 00006718 tss.ss2: resw 1 31128 0000671A resw 1 31129 ; tss offset 28 31130 0000671C tss.CR3: resd 1 31131 00006720 tss.eip: resd 1 31132 00006724 tss.eflags: resd 1 31133 ; tss offset 40 31134 00006728 tss.eax: resd 1 31135 0000672C tss.ecx: resd 1 31136 00006730 tss.edx: resd 1 31137 00006734 tss.ebx: resd 1 31138 00006738 tss.esp: resd 1 31139 0000673C tss.ebp: resd 1 31140 00006740 tss.esi: resd 1 31141 00006744 tss.edi: resd 1 31142 ; tss offset 72 31143 00006748 tss.ES: resw 1 31144 0000674A resw 1 31145 0000674C tss.CS: resw 1 31146 0000674E resw 1 31147 00006750 tss.SS: resw 1 31148 00006752 resw 1 31149 00006754 tss.DS: resw 1 31150 00006756 resw 1 31151 00006758 tss.FS: resw 1 31152 0000675A resw 1 31153 0000675C tss.GS: resw 1 31154 0000675E resw 1 31155 00006760 tss.LDTR: resw 1 31156 00006762 resw 1 31157 ; tss offset 100 31158 00006764 resw 1 31159 00006766 tss.IOPB: resw 1 31160 ; tss offset 104 31161 tss_end: 31162 31163 00006768 k_page_dir: resd 1 ; Kernel's (System) Page Directory address 31164 ; (Physical address = Virtual address) 31165 0000676C memory_size: resd 1 ; memory size in pages 31166 00006770 free_pages: resd 1 ; number of free pages 31167 00006774 next_page: resd 1 ; offset value in M.A.T. for 31168 ; first free page search 31169 00006778 last_page: resd 1 ; offset value in M.A.T. which 31170 ; next free page search will be 31171 ; stopped after it. (end of M.A.T.) 31172 0000677C first_page: resd 1 ; offset value in M.A.T. which 31173 ; first free page search 31174 ; will be started on it. (for user) 31175 00006780 mat_size: resd 1 ; Memory Allocation Table size in pages 31176 31177 ;;; 31178 ; 02/09/2014 (Retro UNIX 386 v1) 31179 ; 04/12/2013 (Retro UNIX 8086 v1) 31180 00006784 CRT_START: resw 1 ; starting address in regen buffer 31181 ; NOTE: active page only 31182 00006786 cursor_posn: resw 8 ; cursor positions for video pages 31183 active_page: 31184 00006796 ptty: resb 1 ; current tty 31185 ; 01/07/2015 31186 00006797 ccolor: resb 1 ; current color attributes ('sysmsg') 31187 ; 26/10/2015 31188 ; 07/09/2014 31189 00006798 ttychr: resw ntty+2 ; Character buffer (multiscreen) 31190 31191 ; 21/08/2014 31192 000067AC tcount: resd 1 31193 31194 ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!) 31195 000067B0 p_time: resd 1 ; present time (for systime & sysmdate) 31196 31197 ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !) 31198 ; (open mode locks for pseudo TTYs) 31199 ; [ major tty locks (return error in any conflicts) ] 31200 000067B4 ttyl: resw ntty+2 ; opening locks for TTYs. 31201 31202 ; 15/04/2015 (Retro UNIX 386 v1) 31203 ; 22/09/2013 (Retro UNIX 8086 v1) 31204 000067C8 wlist: resb ntty+2 ; wait channel list (0 to 9 for TTYs) 31205 ; 15/04/2015 (Retro UNIX 386 v1) 31206 ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h 31207 ;; 0 means serial port is not available 31208 ;;comprm: ; 25/06/2014 31209 000067D2 com1p: resb 1 ;;0E3h 31210 000067D3 com2p: resb 1 ;;0E3h 31211 31212 ; 17/11/2015 31213 ; request for response (from the terminal) 31214 000067D4 req_resp: resw 1 31215 ; 07/11/2015 31216 000067D6 ccomport: resb 1 ; current COM (serial) port 31217 ; (0= COM1, 1= COM2) 31218 ; 09/11/2015 31219 000067D7 comqr: resb 1 ; 'query or response' sign (u9.s, 'sndc') 31220 ; 07/11/2015 31221 000067D8 rchar: resw 1 ; last received char for COM 1 and COM 2 31222 000067DA schar: resw 1 ; last sent char for COM 1 and COM 2 31223 31224 ; 23/10/2015 31225 ; SERIAL PORTS - COMMUNICATION MODES 31226 ; (Retro UNIX 386 v1 feature only!) 31227 ; 0 - command mode (default/initial mode) 31228 ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars) 31229 ;;; communication modes for future versions: 31230 ; // 2 - keyboard mode (ascii+scancode input) 31231 ; // 3 - mouse mode 31232 ; // 4 - device control (output) mode 31233 ; VALID COMMANDS for current version: 31234 ; 'LOGIN' 31235 ; Login request: db 0FFh, 'LOGIN', 0 31236 ; ("Retro UNIX 386 v1 terminal requests login") 31237 ; Login response: db 0FFh, 'login', 0 31238 ; ("login request accepted, wait for login prompt") 31239 ; When a login requests is received and acknowledged (by 31240 ; serial port interrupt handler (communication procedure), 31241 ; Retro UNIX 386 v1 operating system will start terminal mode 31242 ; (login procedure) by changing comm. mode to 1 (terminal mode) 31243 ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2) 31244 ; 31245 ; 'sys connect' system call is used to change communication mode 31246 ; except 'LOGIN' command which is used to start terminal mode 31247 ; by using (COM port) terminal. 31248 31249 ;com1own: resb 1 ; COM1 owner (u.uno) 31250 ;com2own: resb 1 ; COM2 owner (u.uno) 31251 ;com1mode: resb 1 ; communication mode for COM1 31252 ;com1com: resb 1 ; communication command for COM1 31253 ;com2mode: resb 1 ; communication mode for COM1 31254 ;com2com resb 1 ; communication command for COM1 31255 ;com1cbufp: resb 8 ; COM1 command buffer char pointer 31256 ;com2cbufp: resb 8 ; COM2 command buffer char pointer 31257 ;com1cbuf: resb 8 ; COM2 command buffer 31258 ;com2cbuf: resb 8 ; COM2 command buffer 31259 31260 ; 22/08/2014 (RTC) 31261 ; (Packed BCD) 31262 000067DC time_seconds: resb 1 31263 000067DD time_minutes: resb 1 31264 000067DE time_hours: resb 1 31265 000067DF date_wday: resb 1 31266 000067E0 date_day: resb 1 31267 000067E1 date_month: resb 1 31268 000067E2 date_year: resb 1 31269 000067E3 date_century: resb 1 31270 31271 %include 'diskbss.s' ; UNINITIALIZED DISK (BIOS) DATA 31272 <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - DISKBSS.INC 31273 <1> ; Last Modification: 12/07/2022 31274 <1> ; ***************************************************************************** 31275 <1> ; (Uninitialized Disk Parameters Data section for 'DISKIO.INC') 31276 <1> ; ***************************************************************************** 31277 <1> ; Ref: Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKBSS.INC - 10/07/2022 31278 <1> 31279 <1> 31280 <1> alignb 2 31281 <1> 31282 <1> ;---------------------------------------- 31283 <1> ; TIMER DATA AREA : 31284 <1> ;---------------------------------------- 31285 <1> 31286 <1> TIMER_LH: ; 16/02/2015 31287 000067E4 <1> TIMER_LOW: resw 1 ; LOW WORD OF TIMER COUNT 31288 000067E6 <1> TIMER_HIGH: resw 1 ; HIGH WORD OF TIMER COUNT 31289 000067E8 <1> TIMER_OFL: resb 1 ; TIMER HAS ROLLED OVER SINCE LAST READ 31290 <1> 31291 <1> ;---------------------------------------- 31292 <1> ; DISKETTE DATA AREAS : 31293 <1> ;---------------------------------------- 31294 <1> 31295 000067E9 <1> SEEK_STATUS: resb 1 31296 000067EA <1> MOTOR_STATUS: resb 1 31297 000067EB <1> MOTOR_COUNT: resb 1 31298 000067EC <1> DSKETTE_STATUS: resb 1 31299 000067ED <1> NEC_STATUS: resb 7 31300 <1> 31301 <1> ;---------------------------------------- 31302 <1> ; ADDITIONAL MEDIA DATA : 31303 <1> ;---------------------------------------- 31304 <1> 31305 000067F4 <1> LASTRATE: resb 1 31306 000067F5 <1> HF_STATUS: resb 1 31307 <1> ;HF_ERROR: resb 1 ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 31308 000067F6 <1> HF_INT_FLAG: resb 1 31309 <1> ;HF_CNTRL: resb 1 ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 31310 <1> ;DSK_STATE: resb 4 31311 000067F7 <1> DSK_STATE: resb 2 ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 31312 000067F9 <1> DSK_TRK: resb 2 31313 <1> 31314 <1> ;---------------------------------------- 31315 <1> ; FIXED DISK DATA AREAS : 31316 <1> ;---------------------------------------- 31317 <1> 31318 000067FB <1> DISK_STATUS1: resb 1 ; FIXED DISK STATUS 31319 000067FC <1> HF_NUM: resb 1 ; COUNT OF FIXED DISK DRIVES 31320 000067FD <1> CONTROL_BYTE: resb 1 ; HEAD CONTROL BYTE 31321 <1> ;@PORT_OFF resb 1 ; RESERVED (PORT OFFSET) 31322 <1> ;port1_off resb 1 ; Hard disk controller 1 - port offset 31323 <1> ;port2_off resb 1 ; Hard disk controller 2 - port offset 31324 <1> 31325 000067FE <1> alignb 4 31326 <1> 31327 <1> ;HF_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 31328 <1> ;HF1_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 31329 <1> HF_TBL_VEC: ; 22/12/2014 31330 00006800 <1> HDPM_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 31331 00006804 <1> HDPS_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 31332 00006808 <1> HDSM_TBL_VEC: resd 1 ; Secondary master disk param. tbl. pointer 31333 0000680C <1> HDSS_TBL_VEC: resd 1 ; Secondary slave disk param. tbl. pointer 31334 <1> 31335 <1> ; 03/01/2015 31336 00006810 <1> LBAMode: resb 1 31337 <1> 31338 <1> ; ***************************************************************************** 31339 31340 ;;; Real Mode Data (10/07/2015 - BSS) 31341 31342 ;alignb 2 31343 31344 ; 02/01/2022 31345 ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data) 31346 31347 ; 17/04/2021 31348 ; (memory page swap parameters are disabled as temporary) 31349 ; 31350 ;; Memory (swap) Data (11/03/2015) 31351 ; 09/03/2015 31352 ;swpq_count: resw 1 ; count of pages on the swap que 31353 ;swp_drv: resd 1 ; logical drive description table address of the swap drive/disk 31354 ;swpd_size: resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 31355 ;swpd_free: resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical) 31356 ;swpd_next: resd 1 ; next free page block 31357 ;swpd_last: resd 1 ; last swap page block 31358 31359 00006811 alignb 4 31360 31361 ; 10/07/2015 31362 ; 28/08/2014 31363 00006814 error_code: resd 1 31364 ; 29/08/2014 31365 00006818 FaultOffset: resd 1 31366 ; 21/09/2015 31367 0000681C PF_Count: resd 1 ; total page fault count 31368 ; (for debugging - page fault analyze) 31369 ; 'page _fault_handler' (memory.s) 31370 ; 'sysgeterr' (u9.s) 31371 ; 23/02/2022 31372 00006820 rtc_ticks: resd 1 ; (temporary! this rtc counter value may be used 31373 ; for a system call in next retro unix 386 version) 31374 ; -2 ticks per second- 31375 ;; 21/08/2015 31376 ;;buffer: resb (nbuf*520) ;; sysdefs.s, ux.s 31377 31378 ; 02/01/2022 31379 %include 'ux.s' ; 12/04/2015 (unix system/user/process data) 31380 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 31381 <1> ; (re-write kernel for test by using previous version without a major defect) 31382 <1> ; **************************************************************************** 31383 <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - ux.s 31384 <1> ; Last Modification: 15/07/2022 31385 <1> ; 31386 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 31387 <1> ; (Modified from 31388 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 31389 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 31390 <1> ; ---------------------------------------------------------------------------- 31391 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 31392 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 31393 <1> ; 31394 <1> ; 31395 <1> ; (Section E10 (17/3/1972) - ux.s) 31396 <1> ; **************************************************************************** 31397 <1> 31398 <1> ; 15/07/2022 31399 <1> ; 08/06/2022 31400 <1> ; 15/05/2022 31401 <1> ; 21/03/2022 31402 <1> ; 27/02/2022 31403 <1> ; 12/01/2022 31404 <1> ; 22/11/2021 (Modification in Runix v1.1 'ux.s' for runix v2 fs compatibility) 31405 <1> ; 18/07/2021 31406 <1> ; 15/07/2021 31407 <1> ; 12/05/2021 31408 <1> ; 09/05/2021 31409 <1> ; 06/05/2021 31410 <1> ; 02/05/2021 31411 <1> ; 26/01/2020 (NASM version of SuperBlock structure in UNIXHDCP.ASM) 31412 <1> 31413 <1> ; 21/12/2019 (UNIXCOPY.COM, UNIXCOPY.ASM, UNIXHDCP.COM, UNIXHDCP.ASM) 31414 <1> ; 19/12/2019 (UNIXHDFS.COM, RUFSHDI.ASM) 31415 <1> ; 01/09/2019 - Retro UNIX 386 v2 SuperBlock 31416 <1> 31417 <1> ; 14/01/2020 - Super Block modification: 31418 <1> ; - Extended sections/divisions (consequental sectors) 31419 <1> ; - (for swapping, configuration, boot space etc.) 31420 <1> 31421 <1> ; 26/01/2020 (unix386.s, ux.s) 31422 <1> ; 14/01/2020 31423 <1> SB.HiddenSects equ SB.BootSectAddr 31424 <1> SB.TotalSects equ SB.VolumeSize 31425 <1> 31426 <1> ; 11/05/2021 (Retro UNIX 386 v2) 31427 <1> ; Super block status byte (byte 0 of SB.status dword) 31428 <1> ; bit 0 - superblock modified flag 31429 <1> ; bit 1 - inode map modified flag 31430 <1> ; bit 2 - free blocks map modified flag 31431 <1> ; bit 3 - inode table modified flag 31432 <1> ;; bit 4 - boot sector modified flag ; 17/08/2021 31433 <1> ; 17/08/2021 31434 <1> ; bit 4 - file data write error (for SB.LastInode) 31435 <1> ; bit 5 - inode table write error (for SB.LastInode) 31436 <1> ; bit 6 - inode map write error (for SB.LastInode) 31437 <1> ; bit 7 - free blocks map write error (for SB.LastInode) 31438 <1> 31439 <1> ; 21/12/2019 31440 <1> ; 19/12/2019 - Retro UNIX 386 v2 HD (071h) partition boot sector 31441 <1> ; (UNIXHDFS.ASM) 31442 <1> ; 04/12/2015 (14 byte file names - Retro UNIX 386 v1.1) 31443 <1> ; 14/07/2015 (8 byte file names - Retro UNIX 8086 v1 & Retro UNIX 386 v1.0) 31444 <1> 31445 <1> bsFSystemID equ 2 ; db 'RUFS' 31446 <1> bsVolumeSerial equ 6 ; dd 0 ; (4 bytes) 31447 <1> bsFDSign equ 10 ; db 'fd' 31448 <1> bsDriveNumber equ 12 ; db 0 ; fd0 or fd1 (0 or 1) 31449 <1> bsReserved equ 13 ; db 0 ; (512 bytes per sector) 31450 <1> bsSecPerTrack equ 14 ; db 18 ; (9 or 15) 31451 <1> bsHeads equ 15 ; db ; 2 31452 <1> bsTracks equ 16 ; dw 80 ; bsCylinders 31453 <1> bs_bf_inode_number equ 18 ; dw 0 ; 0 or Boot/Startup File I-Number 31454 <1> bsInfoEndsign equ 20 ; db '@' 31455 <1> ; 21/12/2019 31456 <1> bsMagic equ 20 ; db '@' 31457 <1> bsPartitionID equ 21 ; db 0 ; db 71h 31458 <1> bsHiddenSects equ 22 ; dd 0 ; Hidden sectors (Boot Sector LBA) 31459 <1> 31460 <1> ; 22/11/2021 - Retro UNIX v2 I-node Flags 31461 <1> ; ------------------------------------------------------------------ 31462 <1> ; UINSTALL.ASM (included in UNIXFDFS.ASM) - 23/01/2020 31463 <1> ; ------------------------------------------------------------------ 31464 <1> 31465 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files 31466 <1> ; 1000000000000000b IFREG - 1 = regular file (8000h) 31467 <1> ; 0100000000000000b IFDIR - 1 = directory (4000h) 31468 <1> ; 0010000000000000b IRSVD - 0 = reserved bit (2000h) ; Mounted flag 31469 <1> ; 0001000000000000b ILARG - large file addressing bit (1000h) 31470 <1> ; 0000100000000000b ISUID - set user id on exec (800h) 31471 <1> ; 0000010000000000b ISGID - set group id on exec (400h) 31472 <1> ; 0000001000000000b IEXTT - 1 = use extents (200h) 31473 <1> ; 0000000100000000b IREAD - read, owner (100h) 31474 <1> ; 0000000010000000b IWRITE - write, owner (80h) 31475 <1> ; 0000000001000000b IEXEC - execute, owner (40h) 31476 <1> ; 0000000000100000b read, group (20h) 31477 <1> ; 0000000000010000b write, group (10h) 31478 <1> ; 0000000000001000b execute, group (08h) 31479 <1> ; 0000000000000100b read, others (04h) 31480 <1> ; 0000000000000010b write, others (02h) 31481 <1> ; 0000000000000001b execute, others (01h) 31482 <1> 31483 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices 31484 <1> ; 1000000000000000b IFREG - 0 = device file (8000h) 31485 <1> ; 0100000000000000b IFBLK - 1 = block device (4000h) 31486 <1> ; 0010000000000000b IFCHR - character special (2000h) -always 1- 31487 <1> ; 0001000000000000b IFIFO - fifo special (1000h) 31488 <1> ; 0000100000000000b IPIPE - pipe special (800h) ; 07/02/2020 31489 <1> ; 0000010000000000b IREDIR - redirected (400h) ; 07/02/2020 31490 <1> ; 0000001000000000b IEXTR - 1 = external device driver (200h) 31491 <1> ; 0000000100000000b IREAD - read, owner (100h) 31492 <1> ; 0000000010000000b IWRITE - write, owner (80h) 31493 <1> ; 0000000001000000b IEXEC - execute, owner (40h) 31494 <1> ; 0000000000100000b read, group (20h) 31495 <1> ; 0000000000010000b write, group (10h) 31496 <1> ; 0000000000001000b execute, group (08h) 31497 <1> ; 0000000000000100b read, others (04h) 31498 <1> ; 0000000000000010b write, others (02h) 31499 <1> ; 0000000000000001b execute, others (01h) 31500 <1> 31501 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 31502 <1> ; (SB structure has been moved from here to 'sysdefs.s' 31503 <1> ; to overcome NASM's bss addressing bug !!!) 31504 <1> ; (('ux.s' bss section addresses are being overlapped 31505 <1> ; when SB structure is defined in 'ux.s')) 31506 <1> 31507 <1> %if 0 31508 <1> 31509 <1> struc SB ; SuperBlock 31510 <1> 31511 <1> .Header: resd 1 31512 <1> ;.HiddenSects: 31513 <1> .BootSectAddr: resd 1 ; Hidden Sectors 31514 <1> ;.TotalSects: 31515 <1> .VolumeSize: resd 1 ; Entire Volume/Partition Size (includes ext. volume) 31516 <1> .Version: resd 1 31517 <1> .BlockSize: resd 1 31518 <1> .InodeCount: resd 1 31519 <1> .FreeMapAddr: resd 1 31520 <1> .FreeMapSize: resd 1 31521 <1> .InodeMapAddr: resd 1 31522 <1> .InodeMapSize: resd 1 31523 <1> .InodeTblAddr: resd 1 31524 <1> .InodeTblSize: resd 1 31525 <1> .FreeInodes: resd 1 31526 <1> .FirstFreeIno: resd 1 31527 <1> .FreeBlocks: resd 1 31528 <1> .FirstFreeBlk: resd 1 31529 <1> .BootSecParms: resb 19 ; v1 31530 <1> .BSExtension: resb 5 ; v2 HDFS 31531 <1> .Status: resb 1 ; 12/05/2021 (system modification status) (*) 31532 <1> .Pdrv: resb 1 ; Physical disk number (index) ; 12/05/2021 (*) 31533 <1> .Uno: resw 1 ; user/process number ; 12/05/2021 (*) 31534 <1> .ModifTime: resd 1 ; (last) modification time (*) 31535 <1> .ExtdVolTbl: resd 1 ; Extended Volume Start/Table Address 31536 <1> .ExtdVolSize: resd 1 ; Extended Volume (swap section etc.) Size 31537 <1> .LBA_rw: resb 1 31538 <1> .ClusterSize: resb 1 31539 <1> .ReadOnly: resb 1 ; (SB will not be written to disk if bit 0 is 1) 31540 <1> .Mounted: resb 1 31541 <1> .MountInode: resd 1 ; double word 31542 <1> .DevMajor: resb 1 31543 <1> .DevMinor: resb 1 31544 <1> .LongName: resb 1 31545 <1> .Direntry32: resb 1 31546 <1> ; 18/07/2021 31547 <1> .FileBuffer: resd 1 31548 <1> .ItabBuffer: resd 1 31549 <1> .ImapBuffer: resd 1 31550 <1> .FmapBuffer: resd 1 31551 <1> ; 15/07/2021 31552 <1> .LastInode: resd 1 31553 <1> ; 02/05/2021 31554 <1> .FmapIndex: resd 1 31555 <1> .ImapIndex: resd 1 31556 <1> .ItableIndex: resd 1 31557 <1> .Reserved: resb 508-148 ; 18/07/2021 31558 <1> .Footer: resd 1 31559 <1> 31560 <1> endstruc 31561 <1> 31562 <1> %endif 31563 <1> 31564 <1> alignb 2 31565 <1> 31566 <1> inode: 31567 <1> ;; 11/03/2013. 31568 <1> ;;Derived from UNIX v1 source code 'inode' structure (ux). 31569 <1> ;;i. 31570 <1> ; 31571 <1> ;i.flgs: resw 1 31572 <1> ;i.nlks: resb 1 31573 <1> ;i.uid: resb 1 31574 <1> ;i.size: resw 1 ; size 31575 <1> ;i.dskp: resw 8 ; 16 bytes 31576 <1> ;i.ctim: resd 1 31577 <1> ;i.mtim: resd 1 31578 <1> ;i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1) 31579 <1> 31580 <1> ; 26/01/2020 31581 <1> ; Retro UNIX 386 v2.0 - Modified UNIX v7 inode model 31582 <1> ; (15/09/2029 .. 18/12/2019) 31583 <1> 31584 00006824 <1> i.flgs: resw 1 ; /* mode and type of file */ 31585 00006826 <1> i.nlks: resw 1 ; /* number of links to file */ 31586 00006828 <1> i.uid: resw 1 ; /* owner's user id */ - 0 to 65535 - 31587 0000682A <1> i.gid: resb 1 ; /* owner's group id */ - o to 255 - 31588 0000682B <1> i.size_h: resb 1 ; /* number of bytes in file */ ; byte 5 31589 0000682C <1> i.size: resd 1 ; size ; /* number of bytes in file */ 31590 00006830 <1> i.dskp: resd 10 ; 40 bytes ; /* disk block addresses */ 31591 00006858 <1> i.atim: resd 1 ; /* time last accessed */ 31592 0000685C <1> i.mtim: resd 1 ; /* time last modified */ 31593 00006860 <1> i.ctim: resd 1 ; /* time created */ 31594 <1> 31595 <1> I_SIZE equ $ - inode 31596 <1> 31597 <1> process: 31598 <1> ; 27/02/2022 31599 <1> ; 12/01/2022 (Retro UNIX 386 v1.2) 31600 <1> ; 06/05/2015 31601 <1> ; 11/03/2013 - 05/02/2014 31602 <1> ;Derived from UNIX v1 source code 'proc' structure (ux). 31603 <1> ;p. 31604 <1> 31605 00006864 <1> p.pid: resw nproc 31606 00006884 <1> p.ppid: resw nproc 31607 <1> ;p.break: resw nproc ; 12/01/2022 (p.break is not used) 31608 000068A4 <1> p.ttyc: resb nproc ; console tty in Retro UNIX 8086 v1. 31609 <1> ; 27/02/2022 (p.waitc is not used) 31610 <1> ;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1. 31611 000068B4 <1> p.link: resb nproc 31612 000068C4 <1> p.stat: resb nproc 31613 <1> 31614 <1> ; 06/05/2015 (Retro UNIX 386 v1 feature only !) 31615 000068D4 <1> p.upage: resd nproc ; Physical address of the process's 31616 <1> ; 'user' structure 31617 <1> 31618 <1> P_SIZE equ $ - process 31619 <1> 31620 <1> ; fsp table (original UNIX v1) 31621 <1> ; 31622 <1> ;Entry 31623 <1> ; 15 0 31624 <1> ; 1 |---|---------------------------------------| 31625 <1> ; |r/w| i-number of open file | 31626 <1> ; |---|---------------------------------------| 31627 <1> ; | device number | 31628 <1> ; |-------------------------------------------| 31629 <1> ; (*) | offset pointer, i.e., r/w pointer to file | 31630 <1> ; |-------------------------------------------| 31631 <1> ; | flag that says | number of processes | 31632 <1> ; | file deleted | that have file open | 31633 <1> ; |-------------------------------------------| 31634 <1> ; 2 | | 31635 <1> ; |-------------------------------------------| 31636 <1> ; | | 31637 <1> ; |-------------------------------------------| 31638 <1> ; | | 31639 <1> ; |-------------------------------------------| 31640 <1> ; | | 31641 <1> ; |-------------------------------------------| 31642 <1> ; 3 | | 31643 <1> ; | | 31644 <1> ; 31645 <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 31646 <1> 31647 <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 31648 <1> 31649 <1> ;Entry 31650 <1> ; 15 7 0 31651 <1> ; 1 |-------------------------------------------| 31652 <1> ; | i-number of open file | 31653 <1> ; |-------------------------------------------| 31654 <1> ; | high word of 32 bit i-number | 31655 <1> ; |-------------------------------------------| 31656 <1> ; | open mode & status | device number | 31657 <1> ; |-------------------------------------------| 31658 <1> ; | reserved byte | open count | 31659 <1> ; |-------------------------------------------| 31660 <1> ; | offset pointer, i.e., r/w pointer to file | 31661 <1> ; |-------------------------------------------| 31662 <1> ; | 64 bit file offset pointer (bit 16-31) | 31663 <1> ; |-------------------------------------------| 31664 <1> ; | 64 bit file offset pointer (bit 32-47) | 31665 <1> ; |-------------------------------------------| 31666 <1> ; | 64 bit file offset pointer (bit 48-63) | 31667 <1> ; |-------------------------------------------| 31668 <1> ; 2 | | 31669 <1> ; |-------------------------------------------| 31670 <1> ; | | 31671 <1> ; |-------------------------------------------| 31672 <1> ; | | 31673 <1> ; |-------------------------------------------| 31674 <1> ; | | 31675 <1> ; |-------------------------------------------| 31676 <1> ; | | 31677 <1> 31678 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 31679 <1> ; (file structure has been moved from here to 'sysdefs.s' 31680 <1> ; to overcome NASM's bss addressing bug !!!) 31681 <1> ; (('ux.s' bss section addresses are being overlapped 31682 <1> ; when file file structure is defined in 'ux.s')) 31683 <1> 31684 <1> %if 0 31685 <1> 31686 <1> ; 22/11/2021 31687 <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision 31688 <1> 31689 <1> struc file ; open files (fsp) structure 31690 <1> .inode: resw 1 ; inode number of open file (32 bit) 31691 <1> .i32: resw 1 ; higher word of inode number (reserved) 31692 <1> .drive: resb 1 ; logical drive (disk) number 31693 <1> .flags: resb 1 ; open mode and status 31694 <1> .count: resb 1 ; number of processes that have file open 31695 <1> ;.rsvd: resb 1 ; reserved byte (for next versions) 31696 <1> .mnt: resb 1 ; mnttab index+1 (0 = not mounted) 31697 <1> .offset: resd 1 ; file offset/pointer (64 bit) 31698 <1> .o64: resd 1 ; higher 32 bit of file offset 31699 <1> .size: ; = 16 31700 <1> endstruc 31701 <1> 31702 <1> %endif 31703 <1> 31704 <1> ; 01/01/2022 31705 <1> ; 22/11/2021 31706 <1> ;fp.size equ file.size 31707 <1> 31708 <1> ; 02/01/2022 31709 00006914 <1> fsp: resb nfiles*16 ; (NFILES*fp.size) 31710 <1> ; 01/01/2022 31711 <1> ; 22/11/2021 (16/05/2021) 31712 <1> ;fsp: resb NFILES*16 ; (NFILES*fp.size) 31713 <1> ; 15/04/2015 31714 <1> ;fsp: resb nfiles*10 ; 11/05/2015 (8 -> 10) 31715 <1> 31716 00006C34 <1> bufp: resd (nbuf+2) ; will be initialized 31717 00006C7C <1> ii: resd 1 ; 22/11/2021 ; 32 bit inode number (high word is 0) 31718 <1> ; 22/11/2021 31719 00006C80 <1> idev: resb 1 ; logical drive number of current inode, [ii] 31720 00006C81 <1> cdev: resb 1 ; current logical drive number for current user 31721 <1> 31722 <1> ; 18/05/2015 31723 <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!) 31724 <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv') 31725 <1> ; 0 -> root device (which has Retro UNIX 8086 v1 file system) 31726 <1> ; 1 -> mounted device (which has Retro UNIX 8086 v1 file system) 31727 <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures) 31728 <1> ; 0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0 31729 <1> ; 1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1 31730 <1> ; 2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h 31731 <1> ; 3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h 31732 <1> ; 4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h 31733 <1> ; 5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h 31734 00006C82 <1> rdev: resb 1 ; root device number ; Retro UNIX 8086 v1 feature only! 31735 <1> ; as above, for physical drives numbers in following table 31736 00006C83 <1> mdev: resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only! 31737 <1> ; 15/04/2015 31738 <1> ;active: resb 1 ; 15/07/2022 31739 <1> ; resb 1 ; 09/06/2015 31740 00006C84 <1> mpid: resw 1 31741 <1> ; 22/11/2021 (32 bit inode numbers) 31742 00006C86 <1> rootdir: resd 1 31743 00006C8A <1> mnti: resd 1 31744 <1> ; 15/05/2022 ; (parent dir inumber of [mnti]) 31745 00006C8E <1> mntp: resd 1 31746 <1> 31747 <1> ; 14/02/2014 31748 <1> ; Major Modification: Retro UNIX 8086 v1 feature only! 31749 <1> ; Single level run queue 31750 <1> ; (in order to solve sleep/wakeup lock) 31751 00006C92 <1> runq: resw 1 31752 00006C94 <1> imod: resb 1 31753 00006C95 <1> imodx: resb 1 ; 09/01/2022 - Retro UNIX 386 v1.2 31754 00006C96 <1> smod: resb 1 31755 00006C97 <1> mmod: resb 1 31756 <1> ; resb 1 ; 09/01/2022 31757 00006C98 <1> sysflg: resb 1 31758 <1> 31759 00006C99 <1> alignb 4 31760 <1> 31761 <1> user: 31762 <1> ; 01/01/2022 31763 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 31764 <1> ; 24/10/2021 31765 <1> ; 18/10/2021 31766 <1> ; 10/06/2021 31767 <1> ; 30/05/2021 31768 <1> ; 29/05/2021 31769 <1> ; 21/05/2021 31770 <1> ; 20/05/2021 31771 <1> ; 16/05/2021 31772 <1> ; 01/05/2021 31773 <1> ; 27/03/2021 31774 <1> ; 17/04/2020, 28/04/2020 31775 <1> ; 25/03/2020, 28/03/2020 31776 <1> ; 20/03/2020, 22/03/2020, 23/03/2020 31777 <1> ; 05/03/2020, 08/03/2020, 14/03/2020 31778 <1> ; 07/02/2020 - Retro UNIX 386 v2 31779 <1> ; 31780 <1> ; 27/02/2017 - TRDOS 386 31781 <1> ; 13/01/2017 - TRDOS 386 31782 <1> ; 10/01/2017 - TRDOS 386 31783 <1> ; 19/12/2016 - TRDOS 386 31784 <1> ; 21/05/2016 - TRDOS 386 (TRDOS v2.0) 31785 <1> ; [u.pri] usage method modification 31786 <1> ; 31787 <1> ; 04/12/2015 - Retro UNIX 386 v1.1 (14 byte file/directory names) 31788 <1> ; 18/10/2015 31789 <1> ; 12/10/2015 31790 <1> ; 21/09/2015 31791 <1> ; 24/07/2015 31792 <1> ; 16/06/2015 31793 <1> ; 09/06/2015 31794 <1> ; 11/05/2015 31795 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications) 31796 <1> ; 10/10/2013 31797 <1> ; 11/03/2013. 31798 <1> ;Derived from UNIX v1 source code 'user' structure (ux). 31799 <1> ;u. 31800 <1> 31801 00006C9C <1> u.sp: resd 1 ; esp (kernel stack at the beginning of 'sysent') 31802 00006CA0 <1> u.usp: resd 1 ; esp (kernel stack points to user's registers) 31803 00006CA4 <1> u.r0: resd 1 ; eax 31804 00006CA8 <1> u.cdir: resw 1 31805 00006CAA <1> resw 1 ; 28/03/2020 - reserved for 32 bit inode number 31806 <1> ;u.cdrv: resw 1 ; 17/04/2020 (dword alignment) 31807 00006CAC <1> u.cdrv: resb 1 ; 01/05/2021 31808 00006CAD <1> resb 1 ; 01/05/2021 (dword alignment) 31809 00006CAE <1> u.fp: resb 10 ; Retro UNIX 386 v1 31810 <1> ;u.fp: resb OPENFILES ; Retro UNIX 386 v2 ; 28/03/2020 31811 <1> u.fsp: ; 16/05/2021 31812 00006CB8 <1> u.fofp: resd 1 ; 16/05/2021 (pointer to fsp entry) 31813 00006CBC <1> u.dirp: resd 1 31814 00006CC0 <1> u.namep: resd 1 31815 00006CC4 <1> u.off: resd 1 31816 <1> ; resd 1 ; 08/03/2020 - Retro UNIX 386 v2 - 64 bit fptr 31817 00006CC8 <1> u.base: resd 1 31818 00006CCC <1> u.count: resd 1 31819 00006CD0 <1> u.nread: resd 1 31820 00006CD4 <1> u.break: resd 1 ; break 31821 <1> ; 16/05/2021 (Retro UNIX 386 v2) 31822 00006CD8 <1> u.mode: resb 1 ; 16/05/2021 (sysread, syswrite, 'rdwr' file mode) 31823 <1> ; 10/01/2017 (TRDOS 386, relocation and dword alignment) 31824 <1> ; tty number (rtty, rcvt, wtty) 31825 00006CD9 <1> u.ttyn: resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only ! 31826 00006CDA <1> u.ttyp: resw 1 31827 00006CDC <1> u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 31828 <1> ;u.pri: resw 1 ; 14/02/2014 31829 00006CEC <1> u.quant: resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant) 31830 00006CED <1> resb 1 ; 17/04/2020 31831 00006CEE <1> u.pri: resb 1 ; Modification: 21/05/2016 (priority levels: 0, 1, 2) 31832 00006CEF <1> resb 1 ; 17/04/2020 31833 <1> ; 10/06/2021 31834 <1> ;u.signal: resw 1 ; 21/05/2021 - Retro UNIX 386 v2 31835 <1> ; resw 1 ; reserved ; 21/05/2021 31836 00006CF0 <1> u.intr: resw 1 31837 00006CF2 <1> u.quit: resw 1 31838 <1> ;u.emt: resw 1 ; 10/10/2013 31839 <1> ;u.ilgins: resw 1 ; 10/01/2017 31840 <1> ;u.cdrv: resw 1 ; cdev ; 17/04/2020 (moved to up) 31841 <1> ;u.uid: resb 1 ; uid 31842 <1> ;u.ruid: resb 1 31843 00006CF4 <1> u.bsys: resb 1 31844 00006CF5 <1> u.uno: resb 1 31845 00006CF6 <1> u.uid: resw 1 ; uid ; 27/03/2021 - Retro UNIX 386 v2 31846 00006CF8 <1> u.ruid: resw 1 ; 16 bit uid 31847 00006CFA <1> u.gid: resb 1 ; gid ; 27/03/2021 - Retro UNIX 386 v2 31848 00006CFB <1> u.rgid: resb 1 31849 <1> ; 20/05/2021 - Retro UNIX 386 v2 31850 00006CFC <1> u.procp: resd 1 ; /* pointer to proc structure */ 31851 00006D00 <1> u.upage: resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only ! 31852 00006D04 <1> u.pgdir: resd 1 ; 09/03/2015 (page dir addr of process) 31853 00006D08 <1> u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process) 31854 00006D0C <1> u.pbase: resd 1 ; 20/05/2015 (physical base/transfer address) 31855 <1> ; 24/10/2021 (32 bit value for Retro UNIX 386 v2) 31856 00006D10 <1> u.pcount: resd 1 ; 20/05/2015 (byte -transfer- count for page) 31857 <1> ;u.pncount: resw 1 31858 <1> ; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir') 31859 <1> ;u.pnbase: resd 1 31860 <1> ; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir') 31861 00006D14 <1> u.rsvd: resw 1 ; 04/12/2021 (dword alignment) 31862 <1> ; 09/06/2015 31863 00006D16 <1> u.kcall: resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign 31864 <1> ; 08/03/2020 (block device read/write flag for 'sioreg') 31865 00006D17 <1> u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite) 31866 <1> ; 24/07/2015 - 24/06/2015 31867 <1> ;u.args: resd 1 ; arguments list (line) offset from start of [u.upage] 31868 <1> ; (arg list/line is from offset [u.args] to 4096 in [u.upage]) 31869 <1> ; ([u.args] points to argument count -argc- address offset) 31870 <1> ; 24/06/2015 31871 <1> ;u.core: resd 1 ; physical start address of user's memory space (for sys exec) 31872 <1> ;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec) 31873 <1> ; last error number 31874 00006D18 <1> u.error: resd 1 ; 28/07/2013 - 09/03/2015 31875 <1> ; Retro UNIX 8086/386 v1 feature only! 31876 <1> ; 21/09/2015 (debugging - page fault analyze) 31877 00006D1C <1> u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr) 31878 <1> ; 29/05/2021 - Retro UNIX 386 v2, 2021 (sleep, psig) 31879 <1> ; u.signal: resd 1 ; unix signal recognition (enabling, accepting) bits 31880 <1> ; u.srb: resb 1 ; signal handling/responding method 31881 <1> ; u.snum: resb 1 ; signal number (last signal number) 31882 <1> ; u.exit: resb 1 ; exit code ; 30/05/2021 - Retro UNIX 386 v2 31883 <1> ; u.s_lock: resb 1 ; signal handling (phase) lock 31884 <1> ; u.s_addr: resd 1 ; Signal Response Byte or signal handler (callback) address 31885 <1> ; u.s_time: resd 1 ; signal time in unix epoch format 31886 <1> ; 19/12/2016 (TRDOS 386) 31887 <1> ; u.tcb: resd 1 ; Timer callback address/flag which will be used by timer int 31888 <1> ; 13/01/2017 (TRDOS 386) 31889 <1> ; u.t_lock: resb 1 ; Timer interrupt (callback) lock (unlocked by 'sysrele') 31890 <1> ; u.t_mode: resb 1 ; running mode during timer interrupt (0= system, 0FFh= user) 31891 <1> ; 26/02/2017 (TRDOS 386) 31892 <1> ; u.irqc: resb 1 ; Count of IRQ callback services (IRQs in use) 31893 <1> ; 28/02/2017 (TRDOS 386) 31894 <1> ; u.irqwait: resb 1 ; IRQ waiting for callback service flag (IRQ number, If > 0) 31895 <1> ; u.r_lock: resb 1 ; 'IRQ callback service is in progress' flag (IRQ lock) 31896 <1> ; u.r_mode: resb 1 ; running mode during hardware interrupt 31897 <1> ; 07/02/2020 - Retro UNIX 386 v2 31898 <1> ; u.redir: resb 1 ; device func redirection permitted by user (if u.redir > 0) 31899 <1> ; 26/02/2020 - Retro UNIX 386 v2 31900 <1> ; u.rwm: resb 1 ; read & write mode for devices/drives, 0 = direct, 1 = fs r/w 31901 <1> ; 24/02/2020 - Retro UNIX 386 v2 31902 <1> ; 24/10/2021 (32 bit value) 31903 <1> ; u.scount: resd 1 ; sub byte count ; 22/03/2020 31904 <1> ; 07/03/2020 - Retro UNIX 386 v2 31905 <1> ; u.bps: resw 1 ; u.bps = bytes per sector, for readi and writei 31906 <1> ; resw 1 ; 24/10/2021 (32 bit value for using with 32 bit registers) 31907 <1> ; 23/03/2020 - Retro UNIX 386 v2 31908 <1> ; u.timeout: resw 1 ; timeout setting (seconds) -for 'sleep'- 31909 <1> ; 28/04/2020 - Retro UNIX 386 v2 31910 <1> ; u.lock: resb 1 ; Device lock flag (bit 0 is for device/disk read/write) 31911 <1> ; 24/04/2020 31912 <1> ; 17/04/2020 - Retro UNIX 386 v2 31913 <1> ; u.ifs: resb 1 ; (current) installable file system driver index number 31914 <1> ; 25/03/2020 31915 <1> ; 20/03/2020 31916 <1> ;u.lcount: resd 1 ; last byte count for 'writei' (for restoring write count) 31917 <1> 31918 <1> ; 08/03/2020 - Retro UNIX 386 v2 ('sioreg, 'readi') 31919 <1> ;u.limit: resd 1 ; disk/file size limit for block device read/write ('sioreg') 31920 <1> ; resd 1 ; 08/03/2020 - 64 bit limit (disk size in bytes) 31921 <1> ; ; 26/02/2020 - Retro UNIX 386 v2 31922 <1> ;u.sector: resd 1 ; current sector (for readi and writei, device r/w) 31923 <1> ;u.buffer: resd 1 ; current buffer (for readi and writei, device r/w) 31924 <1> ; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup) 31925 <1> ;u.devmm: resw 1 ; device major (hb) and minor (lb) numbers 31926 <1> ;u.zero: resw 1 ; 14/03/2020 - Must be ZERO for current version 31927 <1> ; 22/03/2020 - Retro UNIX 386 v2 (sleep, wakeup) 31928 <1> ; u.device: resd 1 ; (blk, chr) device description table (entry) address 31929 <1> ; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup) 31930 <1> ; u.function: resd 1 ; device function (read, write) 31931 <1> ; 22/03/2020 - Retro UNIX 386 v2, 2020 (readi, writei) 31932 <1> ; u.buffer: resd 1 ; for saving buffer header address for 'poke' 31933 <1> ; u.inode: resw 1 ; for saving inode number of current (device) inode 31934 <1> ; resw 1 ; 18/10/2021 Retro UNIX 386 v2 - 32 bit inode number 31935 <1> ; u.idev: resb 1 ; for saving logical drv number of current (dev) inode 31936 <1> ; 04/12/2021 31937 <1> ; u.rsvd2: resw 1 ; (for dword alignment) 31938 <1> ; 27/02/2017 (TRDOS 386) 31939 <1> ;; 31/12/2021 - temporary ! 31940 <1> ; u.fpsave: resb 1 ; TRDOS 386, 'save/restore FPU registers' flag 31941 <1> alignb 4 31942 <1> ; !! wrong sizing in TRDOS 386 v2.0.4 (in 'ubss.s', 28/02/2017) !! 31943 <1> ;u.fpregs: resb 94 ; 94 byte area for saving and restoring FPU registers 31944 <1> ; 30/05/2021 - Retro UNIX 386 v2 31945 <1> ; u.fpregs: resb 108 ; 108 byte area for saving and restoring FPU registers 31946 <1> alignb 4 31947 <1> 31948 <1> U_SIZE equ $ - user 31949 <1> 31950 <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec') 31951 00006D20 <1> pcore: resd 1 ; physical start address of user's memory space (for sys exec) 31952 00006D24 <1> ecore: resd 1 ; physical start address of user's memory space (for sys exec) 31953 00006D28 <1> nbase: resd 1 ; physical base address for 'namei' & 'sysexec' 31954 <1> ;ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec' 31955 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'ncount') 31956 00006D2C <1> ncount: resd 1 ; remain byte count in page for 'namei' & 'sysexec' 31957 <1> ;argc: resw 1 ; argument count for 'sysexec' 31958 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'argc') 31959 00006D30 <1> argc: resd 1 ; argument count for 'sysexec' 31960 00006D34 <1> argv: resd 1 ; argument list (recent) address for 'sysexec' 31961 <1> 31962 <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning 31963 <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1 31964 00006D38 <1> rw: resb 1 ;; Read/Write sign (iget) 31965 00006D39 <1> rwdsk: resb 1 ;; Read/Write function number (diskio) - 16/06/2015 31966 00006D3A <1> mget_rw: resb 1 ; 22/11/2021 31967 00006D3B <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015 31968 <1> 31969 <1> ; 08/06/2022 - (BugFix) ! (level: resd 0) ! 31970 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility 31971 00006D3C <1> level: resd 1 ; level, level+1, level+2, level+3 ; for 'mget' procedure 31972 <1> 31973 <1> ; (02/01/2022) 31974 <1> ; 27/11/2021 31975 <1> ; these are will be used for disk block allocation ('alloc' proc) 31976 <1> free_map_offset: 31977 00006D40 <1> resd 1 31978 00006D44 <1> free_map_index: resd 1 31979 <1> free_map_sector: 31980 00006D48 <1> resd 1 31981 <1> ;free_map_buffer: 31982 <1> ; resd 1 31983 <1> 31984 <1> ; 12/01/2022 31985 <1> ; 27/11/2021 - temporary ! 31986 <1> ;s.time: resd 1 31987 <1> 31988 <1> ;alignb 4 31989 <1> 31990 <1> ; (02/01/2022) 31991 <1> ; 22/08/2015 31992 <1> ;buffer: resb nbuf * 520 31993 <1> 31994 00006D4C <1> sb0: resd 2 31995 <1> ;s: 31996 <1> ; (root disk) super block buffer 31997 <1> systm: 31998 <1> ; 27/11/2021 - Retro UNIX 386 v2 compatible super block 31999 <1> ; 13/11/2015 (Retro UNIX 386 v1) 32000 <1> ; 11/03/2013. 32001 <1> ;Derived from UNIX v1 source code 'systm' structure (ux). 32002 <1> ;s. 32003 <1> 32004 <1> ;resw 1 32005 <1> ;resb 360 ; 2880 sectors ; original UNIX v1 value: 128 32006 <1> ;resw 1 32007 <1> ;resb 32 ; 256+40 inodes ; original UNIX v1 value: 64 32008 <1> ;s.time: resd 1 32009 <1> ;s.syst: resd 1 32010 <1> ;s.wait_: resd 1 ; wait 32011 <1> ;s.idlet: resd 1 32012 <1> ;s.chrgt: resd 1 32013 <1> ;s.drerr: resw 1 32014 <1> 32015 <1> ; 27/11/2021 32016 00006D54 <1> resb 512 32017 <1> 32018 <1> ;S_SIZE equ $ - systm 32019 <1> 32020 <1> ;resb 512-S_SIZE ; 03/06/2015 32021 <1> 32022 00006F54 <1> sb1: resd 2 32023 <1> ; (mounted disk) super block buffer 32024 <1> mount: 32025 00006F5C <1> resb 512 ; 03/06/2015 32026 <1> 32027 <1> ; 21/03/2022 32028 <1> ; hard disk masterboot sector buffer 32029 0000715C <1> mbrbuf: resd 2 32030 00007164 <1> resb 512 32031 <1> 32032 <1> ; 10/01/2022 32033 00007364 <1> dbli_buf: resb 512 ; double indir ptr buff for 'itrunc', 'tloop' 32034 00007564 <1> trpi_buf: resb 512 ; triple indir ptr buff for 'itrunc', 'tloop' 32035 <1> 32036 <1> ;/ ux -- unix 32037 <1> ; 32038 <1> ;systm: 32039 <1> ; 32040 <1> ; .=.+2 32041 <1> ; .=.+128. 32042 <1> ; .=.+2 32043 <1> ; .=.+64. 32044 <1> ; s.time: .=.+4 32045 <1> ; s.syst: .=.+4 32046 <1> ; s.wait: .=.+4 32047 <1> ; s.idlet:.=.+4 32048 <1> ; s.chrgt:.=.+4 32049 <1> ; s.drerr:.=.+2 32050 <1> ;inode: 32051 <1> ; i.flgs: .=.+2 32052 <1> ; i.nlks: .=.+1 32053 <1> ; i.uid: .=.+1 32054 <1> ; i.size: .=.+2 32055 <1> ; i.dskp: .=.+16. 32056 <1> ; i.ctim: .=.+4 32057 <1> ; i.mtim: .=.+4 32058 <1> ; . = inode+32. 32059 <1> ;mount: .=.+1024. 32060 <1> ;proc: 32061 <1> ; p.pid: .=.+[2*nproc] 32062 <1> ; p.dska: .=.+[2*nproc] 32063 <1> ; p.ppid: .=.+[2*nproc] 32064 <1> ; p.break:.=.+[2*nproc] 32065 <1> ; p.link: .=.+nproc 32066 <1> ; p.stat: .=.+nproc 32067 <1> ;tty: 32068 <1> ; . = .+[ntty*8.] 32069 <1> ;fsp: .=.+[nfiles*8.] 32070 <1> ;bufp: .=.+[nbuf*2]+6 32071 <1> ;sb0: .=.+8 32072 <1> ;sb1: .=.+8 32073 <1> ;swp: .=.+8 32074 <1> ;ii: .=.+2 32075 <1> ;idev: .=.+2 32076 <1> ;cdev: .=.+2 32077 <1> ;deverr: .=.+12. 32078 <1> ;active: .=.+2 32079 <1> ;rfap: .=.+2 32080 <1> ;rkap: .=.+2 32081 <1> ;tcap: .=.+2 32082 <1> ;tcstate:.=.+2 32083 <1> ;tcerrc: .=.+2 32084 <1> ;mnti: .=.+2 32085 <1> ;mntd: .=.+2 32086 <1> ;mpid: .=.+2 32087 <1> ;clockp: .=.+2 32088 <1> ;rootdir:.=.+2 32089 <1> ;toutt: .=.+16. 32090 <1> ;touts: .=.+32. 32091 <1> ;runq: .=.+6 32092 <1> ; 32093 <1> ;wlist: .=.+40. 32094 <1> ;cc: .=.+30. 32095 <1> ;cf: .=.+31. 32096 <1> ;cl: .=.+31. 32097 <1> ;clist: .=.+510. 32098 <1> ;imod: .=.+1 32099 <1> ;smod: .=.+1 32100 <1> ;mmod: .=.+1 32101 <1> ;uquant: .=.+1 32102 <1> ;sysflg: .=.+1 32103 <1> ;pptiflg:.=.+1 32104 <1> ;ttyoch: .=.+1 32105 <1> ; .even 32106 <1> ; .=.+100.; sstack: 32107 <1> ;buffer: .=.+[ntty*140.] 32108 <1> ; .=.+[nbuf*520.] 32109 <1> ; 32110 <1> ; . = core-64. 32111 <1> ;user: 32112 <1> ; u.sp: .=.+2 32113 <1> ; u.usp: .=.+2 32114 <1> ; u.r0: .=.+2 32115 <1> ; u.cdir: .=.+2 32116 <1> ; u.fp: .=.+10. 32117 <1> ; u.fofp: .=.+2 32118 <1> ; u.dirp: .=.+2 32119 <1> ; u.namep: .=.+2 32120 <1> ; u.off: .=.+2 32121 <1> ; u.base: .=.+2 32122 <1> ; u.count: .=.+2 32123 <1> ; u.nread: .=.+2 32124 <1> ; u.break: .=.+2 32125 <1> ; u.ttyp: .=.+2 32126 <1> ; u.dirbuf:.=.+10. 32127 <1> ; u.pri: .=.+2 32128 <1> ; u.intr: .=.+2 32129 <1> ; u.quit: .=.+2 32130 <1> ; u.emt: .=.+2 32131 <1> ; u.ilgins:.=.+2 32132 <1> ; u.cdev: .=.+2 32133 <1> ; u.uid: .=.+1 32134 <1> ; u.ruid: .=.+1 32135 <1> ; u.bsys: .=.+1 32136 <1> ; u.uno: .=.+1 32137 <1> ;. = core 32138 32139 ; 27/12/2021 32140 00007764 buffer: resb (nbuf*520) 32141 32142 bss_end: 32143 32144 ; 12/12/2021 32145 BSS_SIZE equ bss_end - bss_start 32146 32147 ; 27/12/2013 32148 _end: ; end of kernel code (and read only data, just before bss)